React组件在prop更改时重新呈现

时间:2018-05-18 15:06:29

标签: javascript reactjs

import React from 'react';
import { render } from 'react-dom';

const x = [];

const App = props => <div style={styles}>{JSON.stringify(x)}</div>;

render(<App queries={x} />, document.getElementById('root'));

setInterval(x => x.push(Math.random()), 1000, x);
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>React App</title>
</head>

<body>
  <div id="root"></div>
</body>

</html>

当我改变作为道具传递给它的对象时,为什么App组件不会重新渲染。

每当我关闭并重新打开React Dev Tools时,它都会显示新的道具。 enter image description here

这里发生了什么?请帮我理解。

谢谢!

2 个答案:

答案 0 :(得分:3)

这种情况下的答案与setState无关。当状态发生变化时,Sure React会自动重新渲染(只要你没有像使用PureComponent那样做,然后改变数组或对象)。但是你正在从根进行渲染,这与反应状态无关,因为你的状态存在于反应之外。

来自react docs on render

  

如果React元素先前已渲染到容器中,则会这样做   对它执行更新,只在必要时改变DOM   反映最新的React元素。

因此需要在根级别再次调用render以使React协调更改。另外,最好制作一个新的对象/数组。因此,在这种情况下,您可以执行x = x.concat(..)然后再次渲染。

let x = [];

const App = props => <div>{props.queries.toString()}</div>;

const renderApp = (queries) => ReactDOM.render(<App queries={queries} />, document.getElementById('root'));

setInterval(() => {
  x = x.concat(Math.random());
  renderApp(x);
}, 1000);

小提琴:https://jsfiddle.net/ferahl/p7zhs55q/1/

当然更常见的事情是在反应组件中使用本地反应状态,但了解这一点很好,如果你没有使用像redux这样的东西,这就是你可以实现一些全局状态的反应。

答案 1 :(得分:2)

将作为props传递的数据进行变换不会触发重新呈现组件。没有观察者注意到那个可能触发它的物体的突变。如果您在组件you need to use state的生命周期内有更改的数据:

import React, {Component} from 'react';
import { render } from 'react-dom';

const x = [];

class App extends Component {
    state = {
        queries: this.props.queries,
    };

    componentDidMount() {
        setInterval(
            () => this.setState(state => ({queries: [...state.queries, Math.random()]}))
        ), 1000);
    }

    render() {
        return <div style={styles}>{JSON.stringify(this.state.queries)}</div>;
    }
}

render(<App queries={x} />, document.getElementById('root'));

此代码将使用通过props传递的查询初始化组件状态。当组件安装时,它将启动间隔,该间隔将向该状态附加新的随机数。调用setState()将触发使用新状态重新渲染。永远不要改变道具。