如何在反应中的组件之间传递useState?

How to pass useState amoung the components in react?

我有一个注册页面和模态组件。在寄存器中有一个 useState 用于模态的可见性。我将它作为道具传递给 Modal。当模式关闭时如何更改注册页面中的 useState 值。

注册页面:

import React, { useState } from 'react'
import {
  CCard,
  CButton,
  CCardBody,
  CCardHeader,
  CCol,
  CForm,
  CFormInput,
  CFormLabel,
  CSpinner,
  CRow,
} from '@coreui/react'
import CIcon from '@coreui/icons-react'
import { cilSend } from '@coreui/icons'
import Alert from 'src/components/Alert'
import Modal from 'src/components/Modal'

const FormControl = () => {
  const [disabled, setDisabled] = useState(false)
  const [visible, setVisible] = useState(false)
  const [email, setEmail] = useState('')
  const [name, setName] = useState('')

  const handleAddMember = async () => {
    try {
      const data = { email, name }

      const _data = await fetch('http://localhost:4000/api/v1/member/register', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer ' + localStorage.getItem('token'),
        },
        body: JSON.stringify(data),
      })

      if (_data.status === 201) {
        setVisible(true)
        setDisabled(false)
      } else if (_data.status === 422) {
        setDisabled(false)
      } else {
        setDisabled(false)
        throw new Error()
      }
    } catch (err) {
      setDisabled(false)
    }
  }

  return (
    <CRow>
      <Modal visible={visible} message="Member added to your community successfully!" />
      <CCol xs={6}>
        <CCard className="mb-4">
          <CCardHeader>
            <strong>Add New Member</strong>
          </CCardHeader>
          <CCardBody>
            <p className="text-medium-emphasis small">
              Fill in the email address field and name field to add a new member to your community.
            </p>
            <CForm>
              <div className="mb-3">
                <CFormLabel>Email address:</CFormLabel>
                <CFormInput
                  type="email"
                  placeholder="name@example.com"
                  onChange={(e) => {
                    setEmail(e.target.value)
                  }}
                />
              </div>
              
              <div className="mb-3">
                <CFormLabel>Name:</CFormLabel>
                <CFormInput
                  type="text"
                  placeholder="Perera's Home"
                  onChange={(e) => {
                    setName(e.target.value)
                  }}
                />
              </div>
              
              <div className="mb-3">
                <CButton color="primary" disabled={disabled} onClick={() => handleAddMember()}>
                  {disabled ? (
                    <CSpinner component="span" className="me-2" size="sm" aria-hidden="true" />
                  ) : (
                    <CIcon icon={cilSend} className="me-2" />
                  )}
                  Submit
                </CButton>
              </div>
            </CForm>
          </CCardBody>
        </CCard>
      </CCol>
    </CRow>
  )
}

export default FormControl

模态组件:

import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { CButton, CModal, CModalBody, CModalFooter, CModalHeader, CModalTitle } from '@coreui/react'

const Modal = (props) => {
  const [visible, setVisible] = useState(props.visible)

  return (
    <CModal alignment="center" visible={visible} onClose={() => setVisible(false)}>
      <CModalHeader>
        <CModalTitle>Success!</CModalTitle>
      </CModalHeader>
      <CModalBody>{props.message}</CModalBody>
      <CModalFooter>
        <CButton color="primary" onClick={() => setVisible(false)}>
          Close
        </CButton>
      </CModalFooter>
    </CModal>
  )
}

Modal.propTypes = {
  visible: PropTypes.bool,
  message: PropTypes.string,
}

export default React.memo(Modal)

您应该只有 一个 visible 状态成员,在父组件或子组件 (Modal) 中,而不是在两个地方。

如果你把它放在父级中,你可以像任何其他道具一样将它传递给子级:

return <Modal visible={visible} setVisible={setVisible}>{/*...*/}</Modal>

Modal 的代码然后可以使用适当的标志调用 props.setVisible

如果您 希望 Modal 能够隐藏自己(而不是显示自己),您可以传递一个调用 setVisible(false) 的包装函数:

const hide = useCallback(() => setVisible(false), [setVisible]);
//                Optional, see below −−−−−−−−−−−−−^^^^^^^^^^
// ...
return <Modal visible={visible} hide={hide}>{/*...*/}</Modal>

...然后 Modal 的代码调用 hide() 来隐藏模式。

(使 setVisible 成为 useCallback 调用中的依赖项是可选的;状态 setter 函数是 稳定的 ;它们在组件的生命周期内不会改变。一些 linters 不够聪明,无法意识到这一点,如果你不包含它可能会唠叨你,但大多数都比那更聪明。)

这是一个高度简化的示例:

const {useState} = React;

const Example = () => {
    const [visible, setVisible] = useState(false);
    return <div>
        <input type="button" value="Open" disabled={visible} onClick={() => setVisible(true)} />
        <Modal visible={visible} setVisible={setVisible} />
    </div>;
};

const Modal = (props) => {
    if (!props.visible) {
        return null;
    }
    return <div className="modal">
        <div>This is the modal</div>
        <input type="button" value="Close" onClick={() => props.setVisible(false)} />
    </div>;
};

ReactDOM.render(<Example />, document.getElementById("root"));
.modal {
    border: 1px solid grey;
    padding: 4px;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

或者使用解构(我通常将解构与 props 一起使用,但它看起来不像你那样):

const {useState} = React;

const Example = () => {
    const [visible, setVisible] = useState(false);
    return <div>
        <input type="button" value="Open" disabled={visible} onClick={() => setVisible(true)} />
        <Modal visible={visible} setVisible={setVisible} />
    </div>;
};

const Modal = ({visible, setVisible}) => {
    if (!visible) {
        return null;
    }
    return <div className="modal">
        <div>This is the modal</div>
        <input type="button" value="Close" onClick={() => setVisible(false)} />
    </div>;
};

ReactDOM.render(<Example />, document.getElementById("root"));
.modal {
    border: 1px solid grey;
    padding: 4px;
}
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

您也可以在模态组件中传递 setVisible,然后在两个组件上使用相同的 setState

 <Modal visible={visible} setVisible={setVisible} message="Member added to your community successfully!" />

像这样使用

props.visible
props.setVisible