【问题标题】:react hooks, cant updating state via props反应钩子,不能通过道具更新状态
【发布时间】:2020-02-25 16:04:00
【问题描述】:

试图通过组件中的内部函数(setVisible) 更新状态变量('visible')。我检查了tutorıal 并做了同样的事情,但在初始化状态后它没有更新。 Sandobx 链接here.

当用户单击 ShowModal 按钮时,props.visible 为真。但是功能组件中可见的值仍然是错误的。 (我已经检查了调试器上的内容)

代码:

import Modal from '../Helpers/AppModal'

    class Streams extends Component {
        constructor(props) {
            super(props)
            this.state = { showModal: false }
        }

        componentDidMount() {
            this.props.getStreams()
        }

        showDeleteModal = (isShow) =>
        {
            this.setState({ showModal: isShow });
        }
        onClickBackdrop = () => {this.setState({ showModal: false });}

        render() {
            return (
                <div>
                    <button onClick={()=> this.showDeleteModal(true)} className="btn btn-danger">Delete</button>

                    <Modal visible={this.state.showModal} onClickBackdrop={this.onClickBackdrop} />
                </div>
            )
        }
    }

AppModal.js:

 const AppModal = (props) => {
  const [visible, setVisible] = useState(props.visible)
  useEffect(() =>{
    setVisible(props.visible)
},[props.visible])

  debugger
  return (
    <Modal visible={visible} fade={true} onClickBackdrop={props.onClickBackdrop}>
            <div className="modal-header">
              <h5 className="modal-title">{props.title}</h5>
            </div>
            <div className="modal-body">
              {props.body}
            </div>
            <div className="modal-footer">
            <React.Fragment>
              <button type="button" className="btn btn-default" onClick={()=>setVisible(false)}>
                Close
              </button>
            </React.Fragment>

            </div>
          </Modal>
  )
}

【问题讨论】:

  • 我认为你应该这样尝试:setVisible(false)
  • @SouvikGhosh 确实有问题

标签: reactjs react-hooks


【解决方案1】:

传递给useState的参数只是初始状态。将prop 传递给它并不意味着state 将与props 同步。您可以设置效果以将这些更改镜像到您的本地状态。

目前您的Modal 只能从本地状态看到visible,更改props 值不会导致Modal 更改

//Inside child
useEffect(() =>{
    setVisible(props.visible)
},[props])

我为什么要在那儿使用props 而不是props.visible

依赖数组的存在是为了保持同步,你告诉react

“嘿,每次其中一个值更改时都会重新运行此效果。”

问题在于React 在新旧props 之间执行浅比较(Object.is),每个render 都会生成一个新的props 对象,这是第一个触发您的效果的对象地方。

React 不知道如何对嵌套的更改做出“反应”。这里真正改变的是props,react 不知道(也不关心)props.visible,将其作为依赖项传递与传递[] 相同

实际上将props作为依赖传递是没有用的,因为props改变了每个渲染你可以省略依赖数组,这将触发每个渲染的效果

useEffect(() => {
    setVisible(props.visible)
})

【讨论】:

  • 当我这样做时,它在第一次单击时工作正常,但在关闭并重新单击按钮后不显示模式
  • 你能在沙箱中发布一个例子吗?您实际上并不需要useState,但我假设您想使用它对吗?
  • 是的,我已经创建了沙箱,希望对您有所帮助; codesandbox.io/embed/interesting-haze-wb2vw?fontsize=14
  • 那是我的错误。我已将 props.visible 作为依赖项传递,但您应该传递 props。更新了答案
  • 顺便说一句,你能告诉我它为什么有效吗,为什么我要在那里使用 props 而不是 probs.visible?
【解决方案2】:

visible 是一个布尔值。

尝试改变你调用setVisible 的方式,如下所示:

setVisible(false)

而不是

setVisible({visible:false})

【讨论】:

    【解决方案3】:

    如果这是一个拨动开关,那么你应该这样做:

    onClick={() => setVisible(!visible)}
    

    然后它会正确地打开/关闭。

    您可能希望更明确地设置初始值:

    const [visible, setVisible] = useState(false);
    

    【讨论】:

    • 完成,但问题仍然存在,我编辑了帖子(AppModal.js)
    • 仅供参考,在 onClick 上将其设置为 false,它只会工作一次。这就是为什么我建议最初将其设置为 false,然后在 onClick() 中使用 !visible 标志。
    • @TyForHelpDude 在您的代码中,您引用 但 appmodal.js 已将其列为 AppModal - 也许更改代码以正确引用它?
    • 它只是一个别名
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 2020-04-19
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    相关资源
    最近更新 更多