I have a page with multiple ChildComponent tags and I would like each ChildComponent to be told which API to call depending on which ChildComponent a user clicks on. The onClick() will open a modal.
What I am noticing is the API call is made twice when the Modal box opens. When i close the Modal box, the API call is made again.
I understand from this post that the behaviour from React is correct – Function being called multiple times in React functional component
Is there another way to architect this so only one axios API call once?
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);
2
Answers
If you are under React 18 there is this error in the reactivity check this post https://taig.medium.com/prevent-react-from-triggering-useeffect-twice-307a475714d7
If I understand your question and your task well I will try to write my solution.
As you have modal control state at parent component and every time it changes it triggers your parent component to rerender and your child component is rerendered as well and since function is an object in JS, so your fetch function will have different links every rerender and your useEffect in ChildComponent will think that your function was changed.
So, I suppose the best solution is to add memo for your child components like
export default memo(ChildComponent)
(you can import memo from ‘react’). And after that you should wrap fetchPosts and handleOnclick with useCallback. You will have something like thatconst fetchPosts = useCallback(() => doSomething(), [])
Hope it helps.