skip to Main Content

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


  1. 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

    Login or Signup to reply.
  2. 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 that const fetchPosts = useCallback(() => doSomething(), [])

    Hope it helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search