componentDidUpdate 没有触发

Posted

技术标签:

【中文标题】componentDidUpdate 没有触发【英文标题】:componentDidUpdate is not firing 【发布时间】:2017-08-15 18:10:18 【问题描述】:

当我使用 react-router 更改路由时是否会触发 componentDidUpdate?我修改了示例代码,但似乎无法正常工作。

我让 home 组件记录了一些文本,但它似乎没有触发。任何帮助表示赞赏,谢谢!

代码:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import 
    BrowserRouter as Router,
    Route,
    Link
 from 'react-router-dom'

const BasicExample = () => (
    <Router>
        <div>
            <ul>
                <li><Link to="/">Home</Link></li>
                <li><Link to="/about">About</Link></li>
                <li><Link to="/topics">Topics</Link></li>
            </ul>

            <hr/>

            <Route exact path="/" component=Home/>
            <Route path="/about" component=About/>
            <Route path="/topics" component=Topics/>
        </div>
    </Router>
)

class Home extends React.Component 
    render() 
        return (<div>
            <h2>Home</h2>
        </div>);
    

    componentDidUpdate() 
        console.log("Updated!");
    



const About = () => (
    <div>
        <h2>About</h2>
    </div>
)

const Topics = ( match ) => (
    <div>
        <h2>Topics</h2>
        <ul>
            <li>
                <Link to=`$match.url/rendering`>
                    Rendering with React
                </Link>
            </li>
            <li>
                <Link to=`$match.url/components`>
                    Components
                </Link>
            </li>
            <li>
                <Link to=`$match.url/props-v-state`>
                    Props v. State
                </Link>
            </li>
        </ul>

        <Route path=`$match.url/:topicId` component=Topic/>
        <Route exact path=match.url render=() => (
            <h3>Please select a topic.</h3>
        )/>
    </div>
)

const Topic = ( match ) => (
    <div>
        <h3>match.params.topicId</h3>
    </div>
)

ReactDOM.render(
  <BasicExample />,
  document.getElementById('root')
);

【问题讨论】:

【参考方案1】:

根据DOC:

更新可能是由 props 或 state 的更改引起的。这些方法 在重新渲染组件时调用:

componentWillReceiveProps()

shouldComponentUpdate()

componentWillUpdate()

渲染()

componentDidUpdate()

componentWillUpdate

componentWillUpdate() 在新渲染之前立即调用 正在接收道具或状态。以此为契机 在更新发生之前进行准备。不调用此方法 用于初始渲染。

在 Home 组件中,您没有定义任何 state 并且您也没有使用任何 props,这就是为什么不会调用 function 的原因。

查看此示例 componentDidUpdate 将在您单击 Click Me 文本时被调用:

class Home extends React.Component 
    
    constructor()
        super();
        this.state = a: false
    

    componentDidUpdate() 
        console.log("Updated!");
    
    
    render() 
        return (
            <div>
               <h2>Home</h2>
               <p onClick=()=>this.setState(a: !this.state.a)>Click Me</p>
            </div>
        );
    



ReactDOM.render(<Home/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

【讨论】:

请注意,componentWillUpdate()componentWillReceiveProps() 现在是 deprecated 对我不起作用。我正在更新构造函数中的状态,但 react-router 仍然没有触发我的 componentDidUpdate【参考方案2】:

建议的小改动:不推荐将对象传递给 setState 方法。使用 prevState 属性并翻转它的值。

class Home extends React.Component 

        constructor()
            super();
            this.state = a: false
        

        componentDidUpdate() 
            console.log("Updated!");
        

        render() 
            return (
                <div>
                   <h2>Home</h2>
                   <p onClick=()=>this.setState((prevState) => (a: !prevState.a))>Click Me</p>
                </div>
            );
        
    


    ReactDOM.render(<Home/>, document.getElementById('app'))

【讨论】:

您能否提供有关“不推荐将对象传递给 setState 方法”的更多信息?我没听说过。 是的。而且我认为“已弃用”不是正确的词。我应该说一个“坏习惯”,我的理解是 React 早在 React 17 就将停止支持将对象传递给 setState 方法。作者在这里很好地涵盖了这个主题:[链接] (daveceddia.com/why-not-modify-react-state-directly)但本质上,状态是不可变的。当您将对象传递给 setState 时,您将直接修改当前状态。这么小的应用程序不会受到影响,但它可能会导致烦人且难以定位的错误。 P.S.,我更新了我推荐的更改,以正确地将调用 setState 隐式返回的对象包装在括号中。在这两个示例之间,您将一个对象传递给 setState ,它直接改变了它的值。我正在返回一个对象,该对象使用 prevState 参数作为缓冲区,根据其最近的状态更改状态的值。 我认为您可能误解了您链接到的文章。文章中的问题是:this.state.cart.push(item.id);问题不是这样的: this.setState(foo: !this.state.foo) 前者直接改变状态。后者使用所有不可变对象。 我找到了您所建议的参考。我不认为你上面的链接涵盖了它。您的链接是关于突变的。您建议反对的问题是在计算 this.setState 的输入时使用 this.state。本文建议不要这样做:itnext.io/react-setstate-usage-and-gotchas-ac10b4e03d60 它说:“由于 setState 的异步性质,不建议使用 this.state 来获取 setState 中的先前状态。相反,始终依赖 prevState 方式”

以上是关于componentDidUpdate 没有触发的主要内容,如果未能解决你的问题,请参考以下文章

使用 componentDidUpdate 在反应中更新状态

在 componentDidUpdate 中无法访问的状态

React面试题(超详细,附答案)

React面试题(超详细,附答案)

componentDidUpdate 中的 prevState 是 currentState?

mapStateToProps,但未调用componentDidUpdate