async/await in react functional component

Viewed 6433

I'm doing something like the following

(https://stackoverflow.com/a/57847874/433570)

 const LowerCard = (props) => {

   let { review_meta, step } = props
   const [component, setComponent] = useState('');
   const {state, editDispatch} = useContext(ReviewMetaEditCardDispatch);

   useEffect(() => {

     // https://stackoverflow.com/a/57847874/433570

     const setDynamicComponent = async () => {
       let DynamicComponent
       switch(state.step) {
       case 'title':
         DynamicComponent = await import('review/react/components/review-meta-edit-card/step/title')
         break
       }

       if (DynamicComponent) {
         setComponent(DynamicComponent.default)
       }
     }

     setDynamicComponent()
   }, []);


   if (!component) {
     return null
   }

   return (
     <View>
       <component/>
     </View>
   )
   }

The above code works, but when I remove [] at the useEffect call, it results in index.js:1 Warning: Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. You can only call Hooks at the top level of your React function.

I'm guessing it's complaining you shouldn't call setComponent (which is a hook) inside useEffect.

How do I overcome this?

2 Answers

You should not use async function directly inside useEffect.

here is my solution see if it works



const LowerCard = props => {
  let {review_meta, step} = props;
  const [component, setComponent] = useState('');
  const {state, editDispatch} = useContext(ReviewMetaEditCardDispatch);

  const setDynamicComponent = useCallback(async () => {
    let DynamicComponent;
    switch (state.step) {
      case 'title':
        DynamicComponent = await import('review/react/components/review-meta-edit-card/step/title');
        break;
    }

    if (DynamicComponent) {
      setComponent(DynamicComponent.default);
    }
  }, [state]);

  useEffect(() => {
    // https://stackoverflow.com/a/57847874/433570
    setDynamicComponent();
  }, [setDynamicComponent]);

  if (!component) {
    return null;
  }

  return (
    <View>
      <component />
    </View>
  );
};


Your dynamic component is using hooks and if you call importedComponent.default React will throw and error error of using hooks inside of useEffect.

Instead, load the component and call .default when you render it.

I've also added state.step to useEffect dependencies array to make sure to re-run the effect if when state.step changes as if on initial render state.step is not title the component will never render as you provided an empty dependencies array

useEffect(() => {
  // same as before
  // ...
  if (DynamicComponent) {
    setComponent(DynamicComponent);
  }
}, [state.step])

if (!component) {
  return null;
}

return (
  <View>
    <component.default />
  </View>
)
Related