0

i have a problem with an hooks.

When i make

 export default function Checkout() { const { readRemoteFile } = usePapaParse(); const [parsedCsvData, setParsedCsvData] = useState([]); const handleReadRemoteFile = file => { readRemoteFile(file, { complete: (results) => { setParsedCsvData(results.data); }, }); }; handleReadRemoteFile(CSVsource); } 

I have an infinite loop but when i make

 export default function Checkout() { const { readRemoteFile } = usePapaParse(); const [parsedCsvData, setParsedCsvData] = useState([]); const handleReadRemoteFile = file => { readRemoteFile(file, { complete: (results) => { console.log(results.data); }, }); }; handleReadRemoteFile(CSVsource); } 

I have'nt the problem.

Have you an idea ? Thank's Yann.

4
  • 3
    Please show your entire component or the entire custom hook and how you're using it. My best guess is that handleReadRemoteFile(CSVsource) is ran on every render (and setParsedCsvData() updates the state, so the component rerenders when the file is read, causing a loop. Commented Feb 9, 2022 at 8:41
  • Sorry, i add the rest of component. Commented Feb 9, 2022 at 8:50
  • @Taxel yep, they might be using useEffect without the second argument of [] to only run it once: reactjs.org/docs/… Commented Feb 9, 2022 at 8:53
  • Thanks, i can resolve the problem with useEffect. Commented Feb 9, 2022 at 9:42

1 Answer 1

1

While the component code you posted is still incomplete (CSVsource is undefined, there's no return), I think the problem is visible now:

You're running handleReadRemoteFile(CSVsource) on every render (because you're calling it directly). When the file is read, you are setting parsedCsvData, which (because state updates and prop updates trigger a rerender) renders the component again, triggering handleReadRemoteFile once again...

So what's the solution?

Data fetching is a classical example of using the useEffect hook. The following code should do what you want

const { readRemoteFile } = usePapaParse(); const [parsedCsvData, setParsedCsvData] = useState([]); useEffect(()=>{ readRemoteFile(CSVSource, { complete: results => setParsedCsvData(results.data); }); }, [CSVsource]); // rerun this whenever CSVSource changes. 

Please read up on the useEffect hook in the React docs.

Note: there's one problem with the code I posted above. When the component is unmounted while the CSV is still loading, you will get an error "state update on unmounted component" as soon as the loading finished. To mitigate this, use the return function of useEffect in combination with a local variable.

So the final code looks like this:

useEffect(()=>{ let stillMounted = true; readRemoteFile(CSVSource, { complete: results => { if(!stillMounted) return; // prevent update on unmounted component setParsedCsvData(results.data); } }); return ()=>stillMounted = false; // this function is ran before the effect is ran again and on unmount }, [CSVsource]); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.