-1

I've got a function which renders results from searching then filtering a seperate json file (not the issue) to map the results into each individual <div>:

renderSearchResults() {
    if (this.state.searchQuery.length > 0) {
        const results = this.searchLocation(this.state.searchQuery);
        if (results.length === 0) {
            return 'No results were found. Try selecting from a list';
        } else {
            return results.slice(0, 10).map((result, i) => {
                return (
                    <div className='trends--searchResultItem' key={i} onClick={() => alert('hjs')}>
                        {`${result.name}, ${result.country}`}
                    </div>
                );
            });
        }

The onClick function should fire another function, but the alert() is there for testing, however this doesn't even work.

If I take away the parenthesis (onClick={alert('hjs')}, then it fire's 1000s of times, and forces the application to crash, which suggest's im completely missing something in getting this to work.

If where the renderSearchResults() function is makes a difference, it's in the render function in a class.

{
    this.state.focused && (
        <div className='trends--searchResults'>
            {this.renderSearchResults()}
        </div>
    )
}

The state.focused is always set to true, so this isn't the issue either.

Thanks in advance!

  • 1
    Firstly, the reason it fires a hundred times when you remove parentheses is because instead of attaching the `alert` function to the `onClick` handler of the div, it simply calls the `alert()` everytime it is mentioned in the code. That is, if you have a function to be called on click you attach it like `onClick={function_name}` (note the lack of `()` which would make it a function call instead of a function reference)...the reason it works in the code above is because it's creating a new anonymous function everytime a new div is rendered (also not a very good thing). – ManavM Jul 20 '18 at 10:03
  • Did you check the console? The first example works fine here. – Ukasha Jul 20 '18 at 10:04
  • Thanks for the info, I was only saying it fired the function to show that it did work, just not in the way it's intended. The console has absolutely nothing either. I've tried to just console.log() tests, but they don't show up in the console either. – James Gower Jul 20 '18 at 10:09

3 Answers3

0

The javascript onclick attribute takes a function as an argument, by passing the alert() method you're creating an endless loop.

When you use an arrow function () => {} the window context is not available, and the alert() method relies on this - that's why it doesn't fire.

Either bind the context to the arrow function or use a function declaration, as explained in this SO answer - Arrow function vs function declaration / expressions: Are they equivalent / exchangeable?

Benjamin Scholtz
  • 823
  • 6
  • 15
  • The alert() was just a test to see if anything worked. I've tried just using console.log() to print something to the console and that doesn't work either. What I really want to do is call another function which is in the class' props, but it won't even let me print something to the console and I can't understand why. – James Gower Jul 20 '18 at 10:16
  • My comment above applies for any method, you need to pass a function, and one that has context. Try a function declaration: `function log() {console.log()}` - then either pass it as is, or just the name of the function `log` – Benjamin Scholtz Jul 20 '18 at 10:52
0

You can call a method on onClick as

 renderSearchResults() {
        if (this.state.searchQuery.length > 0) {
            const results = this.searchLocation(this.state.searchQuery);
            if (results.length === 0) {
                return 'No results were found. Try selecting from a list';
            } else {
                return results.slice(0, 10).map((result, i) => {
                    return (
                        <div className='trends--searchResultItem' key={i} onClick={this.eventHandler}>
                            {`${result.name}, ${result.country}`}
                        </div>
                    );
                });
            }
   }
Harikrishnan
  • 1,097
  • 8
  • 13
0

Well for anyone else that may happen to stumble across this with the same problem, it was that when the input lost focus with onBlur, the div containing the was unmounted. This is because it only rendered when the focused state was true, which was set when the input was focused.

Long story short, you can't reference a function on an unmounted component. School boy error to not check that, wasted hours figuring this one out!