react modal无法使用useState钩子打开

时间:2020-09-15 23:16:29

标签: reactjs

我有一个呈现react-modal的组件,我的问题是react-modal无法打开。 modalFileNameOpen useState属性设置不正确。

const [modalFileNameOpen, setmodalFileNameOpen] = useState(false)

const handleFileNameChangeClick = () => {
    console.log(modalFileNameOpen)    // set to false
    setmodalFileNameOpen(true)     // this does not set the `modalFileNameOpen` to true. 
    console.log(modalFileNameOpen)    // is still false
}

return (
<div className="container-fluid">
    <input type="button" className="btn" onClick={handleFileNameChangeClick} value="Rename File"></input>

    <ModalFileName modalFileNameOpen={modalFileNameOpen} />

  </div>
)

我还有另一个组成部分ModalFileName

import React, { useState } from 'react';
import Modal from 'react-modal';
Modal.setAppElement('#root');
const ModalFileName = ({ modalFileNameOpen }) => {
    const [modalIsOpen, setModalIsOpen] = useState(modalFileNameOpen)

    return (
        <Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)}>
            <div>
                <h1>File Name Change</h1>
                <div>
                    <button onClick={() => setModalIsOpen(false)}>Close</button>

                </div>
            </div>
        </Modal>
    )
}

export default ModalFileName;

1 个答案:

答案 0 :(得分:1)

这是您似乎想要实现的目标的最小示例。

这是将状态拉到父级并将处理程序函数传递给子级的基本说明。在您的代码中,您试图通过基于父级的状态在子级中声明一个新状态来进行此操作,这会导致不必要的重复和可能的状态冲突。

我们声明了模态状态和设置器以及一个基本的处理函数:

const [openModal, setOpenModal] = useState(false);

  const toggleModal = () => {
    setOpenModal(!openModal);
  }

然后,我们根据当前状态值有条件地渲染模态分量。如果openModal为假,则渲染按钮以将其打开,否则渲染Modal组件,并将处理函数toggleModal传递给它作为道具。

// if openModal is false render the button, else render our modal
{!openModal ?
   <button type="button" onClick={toggleModal}>Open Modal</button>
   : <Modal handler={toggleModal} />
}

如果渲染了模态,它将接收处理程序(在此处通过解构function Modal({handler}) {...进行检索)并将其分配给模态上关闭按钮的onClick

function Modal({handler}) {

  return (
    <div className="modal" >
      <p>I'm a modal</p>
      <button type="button" onClick={handler}>Close Modal</button>
    </div>
  )
}

工作示例

body {
  padding: 0;
  margin: 0;
}

.container {
  position: relative;
  height: 100vh;
  width: 100vw;
  background: gray;
}

.modal {
  height: 50vh;
  width: 50vw;
  position: absolute;
  top: 25%;
  left: 50%;
  transform: translateX(-50%);
  background-color: aqua;
 }
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
  const {useState} = React;

function App() {
  const [openModal, setOpenModal] = useState(false);

  const toggleModal = () => {
    setOpenModal(!openModal);
  }

  return (
    <div className="container">
      {!openModal ?
      <button type="button" onClick={toggleModal}>Open Modal</button>
      : <Modal handler={toggleModal} />
      }
    </div>
  )
}

function Modal({handler}) {

  return (
    <div className="modal" >
      <p>I'm a modal</p>
      <button type="button" onClick={handler}>Close Modal</button>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('App'));
 </script>


一些笔记

如果在console.log()通话之前和之后setOpenModal(),您将获得与问题相同的结果;它将打印出与输入渲染时相同的值。如果不存在问题,则说明您已经改变了状态。从Docs

请不要直接更改this.state,因为之后调用setState()可能会替换您所做的更改。将this.state视为不可变。

const [openModal, setOpenModal] = useState(false);

  const toggleModal = () => {
    console.log(openModal);   // prints the value of openModal on entering render
    setOpenModal(!openModal); // sets openModal to !openModal
    console.log(openModal);   // prints the value of openModal on entering render 
  }

此外,您可能希望将参数传递给传递的处理程序(可以说,close按钮应始终将openModal设置为false,而不希望切换以将其关闭)。 / p>

为此,您只需在处理函数中接受一个参数即可。

const toggleModal = (newState) => {
    setOpenModal(newState);
  }

并将其传递给您的onClick通话。

<button type="button" onClick={() => toggleModal(true)}>Open Modal</button>
function Modal({handler}) {

  return (
    <div className="modal" >
      <p>I'm a modal</p>
        <button type="button" onClick={() => handler(false)}>Close Modal</button>
    </div>
  )
}