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);
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
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 likeconst fetchPosts = useCallback(() => doSomething(), [])
Hope it helps.