Home > OS >  Rerender FunctionComponent when prop gets set with same value
Rerender FunctionComponent when prop gets set with same value

Time:08-09

I'm currently trying to implement some kind of modal (I'm aware that there is a bunch of libraries for that). The real code is much more complex because of a bunch of animation stuff, but it boils down to this (also see this Stackblitz):

const Modal: React.FunctionComponent<{ visible?: boolean }> = ({
  visible,
}) => {
  const [isVisible, setIsVisible] = React.useState(visible);

  React.useEffect(() => setIsVisible(visible), [visible]);

  if (!isVisible) {
    return null;
  }

  return (
    <div>
      I'm visible <button onClick={() => setIsVisible(false)}>Close</button>
    </div>
  );
};

const App: React.FunctionComponent = () => {
  const [showModal, setShowModal] = React.useState(false);

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Show modal</button>
      <Modal visible={showModal} />
    </div>
  );
}

The first time the parent component sets the visible property it works without a problem. But when I close the "modal" and want to set the property again it does not show up again, because the property from the point of view of the "modal" didn't actually change.

Is there a way to always rerender a FunctionComponent when a property gets touched even if the value didn't change?

CodePudding user response:

Have you try this:

const Modal: React.FunctionComponent<{ visible?: boolean }> = ({
  visible,
  setIsVisible
}) => {

  if (!isVisible) {
    return null;
  }

  return (
    <div>
      I'm visible <button onClick={() => setIsVisible(false)}>Close</button>
    </div>
  );
};

const App: React.FunctionComponent = () => {
  const [showModal, setShowModal] = React.useState(false);

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Show modal</button>
      <Modal visible={showModal} setIsVisible={setShowModal} />
    </div>
  );
}

It will then re-render also your parent component, because they share the same state

CodePudding user response:

you're trying changing the value in the child element, this does not get reflected in the parent My suggestion is that to close the modal from parent itself which reduces the code complexity and there is only single source of data here

export const Modal: React.FunctionComponent<{ visible?: boolean , onClose }> = ({
  visible,onClose
}) => {
  const [isVisible, setIsVisible] = React.useState(visible);

  React.useEffect(() => setIsVisible(visible), [visible]);

  if (!isVisible) {
    return null;
  }

  return (
    <div>
      I'm visible <button onClick={() => onClose()}>Close</button>
    </div>
  );
};

  <Modal visible={showModal} onClose={()=>setShowModal(false)} />

working example https://stackblitz.com/edit/react-ts-heiqak?file=Modal.tsx,App.tsx,index.html

  • Related