【问题标题】:React component not re-rendering when state changes状态更改时反应组件不重新渲染
【发布时间】:2019-04-03 15:27:36
【问题描述】:

我有一个基于 url 的 react 组件应该导入一些数据,然后将其显示在另一个子组件中。当页面首次加载时,它会将初始数据加载为componentDidMount() 中的组件状态。至于进一步的 url 更改,它们在componentDidUpdate() 中处理 导出默认类 Info 扩展 React.Component{

constructor(props){
    super(props);
    this.state={
        element:null
    }
}

componentDidMount(){
    switch(this.props.match.params.id){
        case 'legende': import('../data/legends.json').then((data)=>{
            this.setState({
                element:(<InfoDisplay data={data.content} />)
            })
        });break;
        case 'istorie': import('../data/history.json').then((data) => {
            this.setState({
                element: (<InfoDisplay data={data.content} />)
            })
        }); break;
    }
}

componentDidUpdate(prevProps){
    if (this.props.match.params.id !== prevProps.match.params.id)
        switch (this.props.match.params.id) {
            case 'legende': import('../data/legends.json').then((data) => {
                this.setState({
                    element: (<InfoDisplay data={data.content} />)
                })
            });
            break;
            case 'istorie': import('../data/history.json').then((data) => {
                this.setState({
                    element: (<InfoDisplay data={data.content} />)
                })
            }); break;
        default: break;
        }
}

render(){
    return (
        <div style={{backgroundImage:`url(${background})`,height:'100vh',overflowX:'hidden',backgroundSize:'cover'}}>
            <Navbar/>
            {this.state.element}
        </div>
        )
    }
}

我的问题是,尽管 switch 语句中的状态更新,组件不会重新渲染。我不知道我的方法有什么问题。任何人都可以帮助我吗?谢谢!

编辑:这是带有shouldComponentUpdate() 而不是componentDidUpdate 的代码:

import React from 'react'
import * as background from '../assets/img/background_main.png';
import Navbar from './Navbar'
import InfoDisplay from './InfoDisplay';

export default class Info extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            element: null
        }
    }

    componentDidMount() {
        switch (this.props.match.params.id) {
            case 'legende': import('../data/legends.json').then((data) => {
                this.setState({
                    element: (<InfoDisplay data={data.content} />)
                })
            }); break;
            case 'istorie': import('../data/history.json').then((data) => {
                this.setState({
                    element: (<InfoDisplay data={data.content} />)
                })
            }); break;
        }
    }

    shouldComponentUpdate(nextProps,nextState) {
        if (this.props.match.params.id !== nextProps.match.params.id && nextProps) {
            switch (nextProps.match.params.id) {
                case 'legende': import('../data/legends.json').then((data) => {
                    this.setState({
                        element: (<InfoDisplay data={data.content} />)
                    })
                }); return true;
                case 'istorie': import('../data/history.json').then((data) => {
                    this.setState({
                        element: (<InfoDisplay data={data.content} />)
                    })
                });return true;
                default: return false;
            }
        }

        return true;
    }

    render() {
        return (
            <div style={{ backgroundImage: `url(${background})`, height: '100vh', overflowX: 'hidden', backgroundSize: 'cover' }}>
                <Navbar />
                {this.state.element}
            </div>
        )
    }
}

【问题讨论】:

  • 你能检查一下在生命周期方法调用任何 setState 之后渲染是否被调用
  • 同时检查所有案例的数据是否不同

标签: javascript json reactjs


【解决方案1】:

您可能想改用shouldComponentUpdate,因为您想要在组件重新渲染之前做一些事情。

检查一下: https://code.likeagirl.io/understanding-react-component-life-cycle-49bf4b8674de

还有这个: http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/

【讨论】:

  • 检查您的解决方案(使用更新的代码编辑帖子),但它仍然不起作用。状态按应有的方式更新,但组件仍未重新渲染
  • 我想我知道这里有什么问题。这可能是由于位置更改阻止了渲染更新。检查这个:reacttraining.com/react-router/web/guides/…
  • 现在不在我的电脑上,所以无法检查。如果我理解正确,将位置作为道具传递给我要渲染的组件应该可以解决我的问题吗?
  • 我想通了。我通过首先将状态中的元素设置为 null 并在将其设置为 shouldComponentUpdate() 中的 JSX 节点后立即强制重新渲染。感谢您的帮助!
【解决方案2】:

您可以真正简化它并使其更简洁,这也应该可以解决您的问题:

在你的渲染中做:

return (
    <div style={{backgroundImage:`url(${background})`,height:'100vh',overflowX:'hidden',backgroundSize:'cover'}}>
        <Navbar/>
        <InfoDisplay data={this.state.data} />
    </div>
    )

然后在您的 componentDidMount 和 componentDidUpdate 中,您所要做的就是根据您的请求将状态数据设置为 data.content:

 case 'legende': import('../data/legends.json').then((data) => {
            this.setState({
                data: data.content,
            });
        });

显然,您还需要更改构造函数才能获得数据:

this.state = {data: null};

希望这会有所帮助。

【讨论】:

  • 我就是这样做的,但由于某种原因它不起作用。状态仍然为空,如果我尝试将数据变量打印到控制台,它将不会打印。打了两遍,别以为是错别字
【解决方案3】:
如果重新渲染完成,

componentDidUpdate() 将被调用 => 事实上,就像你说的那样,没有重新渲染,因为你从不调用任何 setState 方法。

我不太确定一个状态是否可以保存 JSX 内容。

也许可以这样尝试:

this.setState({
    element: data.content
})

==

<div style={{backgroundImage:`url(${background})`,height:'100vh',overflowX:'hidden',backgroundSize:'cover'}}>
    <Navbar/>
    <InfoDisplay data={this.state.element} />
</div>

希望您通过此信息找到您的错误

【讨论】:

  • JSX 基本上是一个 DOMNode 对象,所以状态可以保存它
【解决方案4】:

如果你想在任何更新上重新渲染,那么你应该使用

componentWillReceiveProps(nextProps){
  this.setState({element:nextProps.data})
}

【讨论】:

  • 它在最后一个版本的 react 中被弃用了。我尽量避免
猜你喜欢
  • 2017-03-24
  • 1970-01-01
  • 2022-07-08
  • 2021-11-07
  • 1970-01-01
  • 2021-01-27
  • 2015-11-03
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多