React Parent/Child State Change Design Question

554 views Asked by At

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?

1

There are 1 answers

2
Ethan Lipkind On BEST ANSWER

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>
)