【问题标题】:componentDidUpdate is not firingcomponentDidUpdate 没有触发
【发布时间】: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')
);

【问题讨论】:

    标签: reactjs react-router


    【解决方案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 方式”
    猜你喜欢
    • 2021-08-05
    • 2019-12-08
    • 1970-01-01
    • 2019-05-25
    • 2020-11-30
    • 2019-04-16
    • 2020-09-30
    • 1970-01-01
    • 2017-12-16
    相关资源
    最近更新 更多