- state 变了 ui 没有变
import React, { Component } from "react";
import "./styles.css";
export default class App extends Component {
constructor(props) {
super(props);
console.log(11111);
// 因为 constructor 里的代码只会在初始化的时候执行一次,所以后面就算 state 更新了,
// this.test 里用到的 state 也还是初始化的
this.test = {
c: this.state.num % 2 === 0 ? "偶数" : "奇数"
};
}
state = {
num: 1
};
handleTest = () => {
this.setState({
num: this.state.num + 1
});
};
render() {
const { num } = this.state;
return (
<div>
<div>{num}</div>
{/* 这里会一直显示奇数,因为 this.test 一直没变 */}
<div onClick={this.handleTest}>{this.test.c}</div>
</div>
);
}
}
解决办法:
将依赖state的数据都放在render 里
import React, { Component } from "react";
import "./styles.css";
export default class App extends Component {
constructor(props) {
super(props);
console.log(11111);
// 因为 constructor 里的代码只会在初始化的时候执行一次,所以后面就算 state 更新了,
// this.test 里用到的 state 也还是初始化的
this.test = {
c: this.state.num % 2 === 0 ? "偶数" : "奇数"
};
}
state = {
num: 1
};
handleTest = () => {
this.setState({
num: this.state.num + 1
});
};
render() {
const { num } = this.state;
const test = {
c: this.state.num % 2 === 0 ? "偶数" : "奇数"
}
return (
<div>
<div>{num}</div>
{/* 这里会一直显示奇数,因为 this.test 一直没变 */}
<div onClick={this.handleTest}>{this.test.c}</div>
{/* 这里会变 */}
<div onClick={this.handleTest}>{test.c}</div>
</div>
);
}
}
- 使用 hooks 父组件传给子组件一个属性值,子组件用这个属性作为初始值的情况,父组件属性变了,子组件里的初始值也不会变;
比如:
- parent.js
const [amount, setAmount] = useState(0)
useEffect(() => {
setAmount(2)
})
return (
<div>
<Child
amount={amount}
/>
</div>
)
- child.js
const Child = (props) => {
const { amount } = props
const [newAmount, setNewAmount] = useState(amount)
// 等价于
// const [newAmount, setNewAmount] = useState(0)
return (
<div>
{newAmount}
</div>
)
}
上面的代码父组件传入 amount 属性给子组件,一开始 amount 为0,所以0就被传入到子组件,子组件把0作为初始值,后面父组件 amount 修改后,子组件的 newAmount 不会再次跟着变化,因为子组件里的 newAmount 是自己的 newAmount,只有通过自己内部的 setNewAmount 修改 才会重新渲染;所以父组件mounted后amount变为2,子组件的 newAmount 还是 0
所以如果想要子组件里的 newAmount 也跟着 父组件的 amount 变化而变化,就要使用 useEffect 监听 amount 然后赋值给 newAmount
- child.js
useEffect(() => {
setNewAmount(amount)
}, [amount])
- 只要父组件传入子组件的属性变了,不管子组件用没用到这个 props,子组件都会重新渲染,只要是 props 改变了,就相当于当前组件 setState 了,锁对于 useState 来说不会恢复初始值