nicetoCyou
nicetoCyou

Reputation: 65

Array being populated with JSX Elements not rendering/updating

This may be a quick fix but I have been racking my brain for the past little while, and could really use another set of eyes to take a look.

Basically I am trying to render an array full of generated JSX elements. I fell like I have done this a million times, but it does not seem to work here.

Heres the code:

import React, { Fragment } from 'react'
import css from './Search.scss';

import Header from '../SectionHeader/Header';
import SearchItem from '../SearchItem/SearchItem';

const Search = (props) => {

  const { coinObject, coinKeys } = props;

  let searchResults = [];                              // Array in question

  const findResults = (searchText) => {
    searchResults = [];                                // Reset the array to blank for each new character typed in input
    for(let i = 0; i < coinKeys.length; i++) {         
      const { FullName } = coinObject[coinKeys[i]];    // App specific logic, not important, or the problem here
      if(FullName.toLowerCase().includes(searchText) && (searchResults.length < 5)) {    
        console.log(FullName, searchText);             // Prints the correct Full name based off of the searched text
        searchResults.push(<SearchItem key={i} searchText={FullName} />);
      }
    }
    console.log(searchResults);                        // Prints the updated array with all react elements
  }

  return (
    <Fragment>
      <Header title='Find Coins!' />
      <div className={css.searchContainer}>
        <div className={css.inputContainer}>
          <input onChange={input => findResults(input.target.value)} className={css.searchInput} type='text' placeholder='Start Typing a Coin'/>
        </div>
        { searchResults }
      </div>
    </Fragment>
  );
}

export default Search;

And the SearchItem Component, which is super simple:

import React from 'react'
import css from './SearchItem.scss';

const SearchItem = (props) => {
  return (
    <div className={css.searchItem}>
      {props.searchText}
    </div>
  )
}

export default SearchItem;

For a little bit of context, this component just gets a giant object of data, and will display the first 5 instances of what matches the input text. I am trying to make one of those search filter things, where as you type it suggests things that match from the data.

The array gets updated, and I can see the JSX objects in the array, they just do not render. I have a feeling it is due to the array not re-rendering?

Any help is much appreciated. Thanks!

Upvotes: 1

Views: 112

Answers (1)

Tholle
Tholle

Reputation: 112897

You could make the Search component into a stateful component and store the searchResults in your state instead, so that when it is updated your component will be re-rendered.

Example

class Search extends React.Component {
  state = { searchResults: [] };

  findResults = searchText => {
    const { coinObject, coinKeys } = this.props;
    const searchResults = [];

    for (let i = 0; i < coinKeys.length; i++) {
      const { FullName } = coinObject[coinKeys[i]];
      if (
        FullName.toLowerCase().includes(searchText) &&
        searchResults.length < 5
      ) {
        searchResults.push(FullName);
      }
    }

    this.setState({ searchResults });
  };

  render() {
    return (
      <Fragment>
        <Header title="Find Coins!" />
        <div className={css.searchContainer}>
          <div className={css.inputContainer}>
            <input
              onChange={event => findResults(event.target.value)}
              className={css.searchInput}
              type="text"
              placeholder="Start Typing a Coin"
            />
          </div>
          {this.state.searchResults.map((fullName, i) => (
            <SearchItem key={i} searchText={fullName} />
          ))}
        </div>
      </Fragment>
    );
  }
}

Upvotes: 1

Related Questions