Home > Back-end >  React prevent re render
React prevent re render

Time:01-21

How should I prevent a re render when I click on onClose to close the modal.

It looks like the dispatch function: dispatch(setActiveStep(0) cause some troubles.

export default function ImportOrderModal(props: ImportOrderModalProps) {
  const { open, onClose } = props
  const {
    orderImport: { activeStep }
  } = useAppSelector((state: RootState) => state)
  const steps = useImportOrderConfig()
  const dispatch = useDispatch()

  React.useEffect(() => {
    getOrdersList()
  }, [])

  const onCloseModal = () => {
    onClose()
    // Force a re render because of activeStep value
    dispatch(setActiveStep(0))
  }

  const getOrdersList = async () => {
    const orders = //API call        
    dispatch(setOrdersList(orders))
  }


  return (
    <Modal open={open} onClose={onCloseModal}>
        <Stepper steps={steps} currentStepNumber={activeStep} />
        <FormSteps />
    </Modal>
  )
}

CodePudding user response:

You can prevent a re-render by using the useEffect() hook and passing in a second argument of an empty array. This will ensure that the effect will only run once when the component mounts. You can also pass in a dependency array that contains any values that, if changed, will trigger the effect to run again.

For example:

useEffect(() => {
  dispatch(setActiveStep(0))
}, [])

In this case, the effect will only run once when the component mounts, and will not re-run when the onClose() function is called.

CodePudding user response:

This block is outside of your useEffect()

const getOrdersList = async () => {
  const orders = //API call
  dispatch(setOrdersList(orders))
}

This will cause rendering troubles.

if you're using an older version of React (<17) that doesn't enforce <React.StrictMode> you can get away with rewriting that as:

useEffect(() => {
  getOrderList
    .then((orders) => dispatch(setOrdersList(orders))
    .catch((error) => console.error(error));
}, [dispatch]);

if you're using a newer version of React (>18) you will have to cleanup your asynchronous call in the cleanup function of your useEffect().

useEffect(() => {
  // This has to be passed down to your fetch/axios call
  const controller = new AbortController();

  getOrderList(controller)
    .then((orders) => dispatch(setOrdersList(orders))
    .catch((error) => console.error(error));

  return () => {
    // This will abort any ongoing async call
    controller.abort();
  }
}, [dispatch]);

For this to make sense I will probably have to write an example of the api call for you as well, if you don't mind I'll use axios for the example but it essentially works the same-ish with .fetch.

const getOrderList = async (controller) => {
  try {
    const { data } = await axios.get("url", { signal: controller.signal });
    return data.orders;
  } catch (e) {
    throw e;
  }
}
  • Related