【问题标题】:How to pass useState amoung the components in react?如何在反应的组件之间传递useState?
【发布时间】:2022-01-01 10:55:59
【问题描述】:

我有一个注册页面和模态组件。在注册中有一个useState 用于模态的可见性。我将它作为道具传递给 Modal。 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)

【问题讨论】:

    标签: javascript reactjs modal-dialog use-state prop


    【解决方案1】:

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

    如果你把它放在 parent 中,你可以像任何其他 prop 一样将它传递给 child:

    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() 来隐藏模态框。

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

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

    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>

    或者使用解构(我通常使用带有道具的解构,但看起来不像你):

    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>

    【讨论】:

    • @NiPoo - 我不使用 PropType(我使用 TypeScript)。 Looking at the lib,看起来真的很通用,PropTypes.func。在 TypeScript 中它会更具体,React.Dispatch&lt;React.SetStateAction&lt;boolean&gt;&gt;.
    • 我使用了&lt;CButton onClick={() =&gt; props.setVisible(false)} /&gt;,但是说TypeError: props.setVisible is not a function会产生错误。
    • @NiPoo - 这部分没问题,所以问题在于你如何将setVisible 传递给Modal。如果你按照我上面显示的那样做,那应该可以。
    • @NiPoo - 我在答案中添加了一个简化示例。
    • @NiPoo - 不用担心!编码愉快!
    【解决方案2】:

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

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

    像这样使用

    props.visible
    props.setVisible
    

    【讨论】:

    • 试试 PropTypes.func 希望它能正常工作@NiPoo
    • 我使用了&lt;CButton onClick={() =&gt; props.setVisible(false)} /&gt;,但是说TypeError: props.setVisible is not a function会产生错误。
    • 你需要在 Modal 组件中传递 setVisible 才能工作setVisible={setVisible} 它没有得到 setVisible
    猜你喜欢
    • 1970-01-01
    • 2020-03-25
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2022-01-21
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多