Не удается обновить состояние родительского компонента с помощью React useState

#javascript #reactjs #frontend

Вопрос:

я сталкиваюсь с этим странным поведением при попытке обновить родительский компонент с помощью функции set для дочернего элемента с реквизитами этот крючок предназначен для открытия и закрытия модального для редактирования элемента

 //PARENT FILE  //hook  const [isEditModalOpen, setEditModalOpen] = useState(false)   //more code...  //modal  {isEditModalOpen amp;amp; lt;EditExcerciseModal setEditModalOpen={setEditModalOpen} isEditModalOpen={isEditModalOpen} /gt;}    

и это дочерний код

 //CHILD FILE  export const EditExcerciseModal = ({setEditModalOpen, excerciseInfo,fetchExcercisesFromRoutine})  //more code etc etc   lt;div className="addExcerciseModalContainer"gt;  lt;span onClick={() =gt;{ setEditModalOpen(false) }} className="xModal"gt;Xlt;/spangt;   

я проверил, и onClick работает. если я изменю родительское состояние вручную, модальный режим будет работать нормально и закроется.

странный случай, когда он работает, — это когда вместо вызова функции set я создаю функцию с параметром setTimeout без времени, как это:

 function closeModal(){   setTimeout(() =gt; { setEditModalOpen(false)}, 0);    }  

есть какие-нибудь идеи? спасибо за помощь

Ответ №1:

Вам нужно создать разделение забот. Модальный состоит из трех частей

  • Модальность своего «Я».
  • Содержание модального.
  • И контейнер из двух.

Вы должны использовать useState() хук и вызывать setEditModalOpen один и тот же содержащий компонент.

Вам нужно убедиться, что вы объявляете и устанавливаете состояние внутри одного и того же компонента.

 // children would be the content of the modal const Modal = ({ children, selector, open, setOpen }) =gt; {  // we need the useEffect hook so that when we change open to false  // the modal component will re-render and the portal will not be created  useEffect(() =gt; {  setOpen(false);  //provide useEffect hook with clean up.  return () =gt; setOpen(true);  }, [selector]);   return open ? createPortal(children, selector) : null; };  export const EditExerciseModal = ({ close }) =gt; {  return (  lt;divgt;  {/* Instead of creating a handler inside this component we can create it in it's parent element */}  lt;span onClick={close}gt;Xlt;/spangt;  {/* Content */}  lt;/divgt;  ); };  export const ModalBtn = () =gt; {  const [isEditModalOpen, setEditModalOpen] = useState(false);  // this is where it all comes together,  // our button element will keep track of the isEditModalOpen variable,  // which in turn will update both child elements  // when true useEffect hook will re-render Modal Component only now it "will" createPortal()  // when our EditExerciseModal alls close it will set change the isEditModalOpen to false  // which will be passed to the Modal component which  // will then cause the component to re-render and not call createPortal()   return (  lt;gt;  lt;button onClick={() =gt; setEditModalOpen(true)}gt;EditExerciseModallt;/buttongt;  {setEditModalOpen amp;amp; (  lt;Modal  open={isEditModalOpen}  setOpen={setEditModalOpen}  selector={'#portal'}gt;  lt;div className='overlay'gt;  lt;EditExerciseModal close={() =gt; setEditModalOpen(false)} /gt;  lt;/divgt;  lt;/Modalgt;  )}  lt;/gt;  ); };  

Комментарии:

1. Спасибо, чувак. Я немного изучу порталы react и попробую это. У вас есть представление о том, почему он работает при использовании в режиме ожидания с задержкой 0 мс? я думаю, это связано с асинхронными вещами? или просто жучок?

2. @Ewcom в каком компоненте находится эта функция?