Function is called multiple times when using useEffect passed to child React component
P粉818561682
P粉818561682 2024-03-30 15:36:26
0
2
511

I have a page with multiple ChildComponent tags, and I want each ChildComponent to be told which API to call based on which ChildComponent the user clicked. onClick() will open a modal.

I noticed that when the modal is opened, the API call is made twice. When I close the modal, the API call will be made again.

What I learned from this post is that React behaves correctly - calling functions multiple times in React functional components

Is there another way to structure this so that there is only one axios API call at a time?

const [posts, setPosts] = useState([]);

export default function ParentComponent() {
    const fetchPosts = useCallback(async () => {
        try {
            const result = await axios(`https://jsonplaceholder.typicode.com/posts`);
            setPosts(result.data.data);
        } catch (error) {
            console.log(error);
        }
    }, []);
}
<ChildComponent
      fetchPosts={fetchPosts}
      onClick={handleOnclick}
/>
const ChildComponent = ({ fetchPosts }) => {
    useEffect(
       () => props.fetchPosts, 
       [props.fetchPosts]
    );
}

export default memo(ChildComponent);

P粉818561682
P粉818561682

reply all(2)
P粉198670603

If you are using React 18, you are getting this error in reactivity, please check this post https://taig.medium.com/prevent-react-from-triggering-useeffect-twice-307a475714d7

P粉005134685

If I understand your problem and task well, I will try to write my solution.

Since you have modal control state on the parent component, every change will trigger your parent component to re-render, and your child components to re-render as well, and since functions are objects in JS, your The fetch function will re-render with a different link every time and your useEffect in ChildComponent will think your function has changed.

So, I think the best solution is to add memo to your child component, like export default memo(ChildComponent) (You can import memo from "react") . After that you should wrap fetchPosts and handleOnclick with useCallback. You'll get something like const fetchPosts = useCallback(() => doSomething(), [])

Hope it helps.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template