javascriptreactjsreact-nativeparent-childreact-native-modal

React Parent/Child State Change Design Question


I have a component with two children, one of them is a button that toggles a state (modalVisible) that decides whether the other child, a modal, is visible.

I'm having trouble sharing the on/off state across the parent and the modal child. I tried keeping the state in the parent and then passing it as a prop to the child, but it wasn't rerendering the child everytime the parent state changed.

<CommentsModal visible={modalVisible} />

Inside CommentsModal.js...

import Modal from 'react-native-modal';
...
const CommentsModal = ({visible}) => {
    const [modalVisible, setModalVisible] = useState(visible);
    ...
    return <Modal visible={modalVisible} />
}

I considered keeping the state entirely in the parent, without passing it into CommentsModal, like so:

function renderModal() {
    if (modalVisible) {
        return <CommentsModal visible={true} />
    } else {
        return <View />
    }
}

But I realized that there has to be a state inside CommentsModal because I need an "X" button that toggles the modal off.

I'm not sure what the best way to do this is... I could do redux, but since there is a dynamic number of these modals; I don't want my store to be that complicated. The only way I can think of is to move all of the modal code into the parent component, then they can share states easily, but it seems dirty to me. Does anyone have a solution?


Solution

  • Your intuition to keep the state in the parent component is correct. To implement the x button all you need is to pass a onClose prop to the modal which would be a function that sets modalVisible to false. so you'll end up with something like this:

    // parent component
    const ParentComponent = () => {
      const [modalVisible, setModalVisible] = useState(false);
      const openModal = () => setModalVisible(true);
      const closeModal = () => setModalVisible(false);
    
      return (
        <div>
          <CommentsModal visible={modalVisible} onClose={closeModal} />
          <button onClick={openModal}>open the modal</button>
          <p>other children here...</p>
        </div>
      )
    }
    
    
    // CommentsModal
    const CommentsModal = (props) => (
      <Modal visible={props.visible}>
        <button onClick={props.onClose}>X</button>
        <p>more modal content here...</p>
      </Modal>
    )