Data Persistence Between Renders in Functional Component

Viewed 424

I'm currently loading more than 2000 objects from a CSV file in a useEffect hook. Each time searchTerm changes, all data in the CSV file is reloaded and filtered. Refer to the code below for details:

  useEffect( () => {
    const asyncLoadWords = async () => {
      const dnd_words = await d3.csv(data_csv);
      const results = dnd_words.filter(wordObject => {
        return wordObject.原词.toLowerCase().includes(searchTerm);
      });
      setSearchResults(results);
    }
    asyncLoadWords();    
  },[searchTerm]);

Is there a way to persist the CSV data between renders? One possible solution I've been thinking about is creating a child component that takes the CSV data as a prop and rerenders via useEffect.

Any input would be greatly appreciated.

1 Answers

I'd recommend having your state be the unfiltered data, and then having the filtered data be a computed value. You can use useMemo to skip recalculating the filter if neither the data nor the search term has changed. And if only the search term changes, then it can recompute the filter using the data that's already loaded.

const Example = () => {
  const [words, setWords] = useState([]);
  useEffect(() => {
    const asyncLoadWords = async () => {
      const dnd_words = await d3.csv(data_csv);
      setWords(dnd_words);
    }
    asyncLoadWords();
  }, []);

  const [searchTerm, setSearchTerm] = useState('');

  const results = useMemo(() => {
    return words.filter(wordObject => {
      return wordObject.原词.toLowerCase().includes(searchTerm);
    });
  }, [words, searchTerm]);

  // etc
}
Related