下面是一个简单的示例:
const { Component } = React
const { render } = ReactDOM
const Label = ({text}) => (<p>{text}</p>)
const Clock = ({ date }) => (
<div>{date.toLocaleTimeString()}</div>
)
class App extends Component {
constructor() {
super()
this.state = {
date: new Date()
}
}
componentWillMount() {
this.interval = setInterval(
() => this.setState({ date: new Date() }),
1000
)
}
componentWillUnmount() {
clearInterval(this.interval)
}
updateTime() {
}
render() {
return (
<div>
<Label text="The current time is:" />
<Clock date={this.state.date} />
</div>
)
}
}
render(<App />, document.querySelector('#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"></div>
这是指向codepen
的链接 this.setState({ date: new Date() })
每秒被调用一次,以当前时间更新Clock。据我所知,setState
在App上调用render方法,这将导致整个组件(包括Label)都被重新渲染。
有没有一种方法可以将日期传递给Clock(使其重新呈现)而又不重新呈现整个App组件?在性能方面,这起了多大作用?
答案 0 :(得分:2)
不可能是您想要的。要将prop传递给子组件,父组件的状态或prop应该以某种方式更改。如您所知,这显然会引发重新渲染,因此所有子级都将重新渲染。要进行更新,在这种情况下,应重新渲染Clock
组件,并进行挂载/挂载,以反映DOM的变化。
如果您的应用程序不是很大,并且没有那么多孩子,则不必担心此问题,因为渲染并不那么昂贵。昂贵的一个是组件的DOM操作。在这里,React会比较实际和虚拟DOM,即使重新渲染也不会卸载/重新安装Label
组件。但是,如果您将Label
组件编写为PureComponent
,则它不会重新呈现。但是要像这样更新Clock
组件,就没有办法。
class Label extends React.PureComponent {
render() {
console.log("rendered");
return (<p>{this.props.text}</p>)
}
}
const Clock = ({ date }) => (
<div>{date.toLocaleTimeString()}</div>
)
class App extends React.Component {
constructor() {
super()
this.state = {
date: new Date()
}
}
componentWillMount() {
this.interval = setInterval(
() => this.setState({ date: new Date() }),
1000
)
}
componentWillUnmount() {
clearInterval(this.interval)
}
updateTime() {
}
render() {
return (
<div>
<Label text="The current time is:" />
<Clock date={this.state.date} />
</div>
)
}
}
答案 1 :(得分:0)
要更新子项而不更新父项时,状态必须在子项中。您可以将状态getter / setter从子级传递给父级,以便能够读取和更新它:
function Child({onMount}) {
const [value, setValue] = useState(0);
useEffect(() => {
onMount([value, setValue]);
}, [onMount, value]);
return (
<div>
{value}
</div>
);
};
function Parent() {
let value = null;
let setValue = null;
const onChildMount = (dataFromChild) => {
value = dataFromChild[0];
setValue = dataFromChild[1];
};
// Call setValue to update child without updating parent
return (
<div>
<Child onMount={onChildMount}/>
</div>
);
};
由于const [value, setValue] = useState(0);
位于Child
中,因此在更新值时仅子组件会重新呈现。另外,由于Parent
在value
收到setValue
和onChildMount
,因此父级可以使用它们来更新子级,而无需重新呈现父级。