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.