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时,它都会显示新的道具。
这里发生了什么?请帮我理解。
谢谢!
答案 0 :(得分:3)
这种情况下的答案与setState无关。当状态发生变化时,Sure React会自动重新渲染(只要你没有像使用PureComponent那样做,然后改变数组或对象)。但是你正在从根进行渲染,这与反应状态无关,因为你的状态存在于反应之外。
如果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()
将触发使用新状态重新渲染。永远不要改变道具。