[英]Component doesn't re-render when Redux state is changed - React
I have RowsCont
with renderRows
我有
RowsCont
与renderRows
renderRows = () => {
let result = [];
const {rows} = this.props;
console.log('RENDER');
console.log(rows);
for(let key in rows){
result.push(<Row={rows[key].id}
onHover={this.onHover}
row={rows[key]}/>);
}
return result;
};
....
render(){<div>{this.renderRows()}</div>}
....
function mapStateToProps(state) {
console.log('mapState');
console.log(state.rows.rows);
return {
rows: state.rows.rows,
}
}
Row Component: 行组件:
render(){
return (
<div>
<div>{this.props.row.id}</div>
<div>{this.props.row.value}</div>
</div>
)
}
Rows is a collection of objects, each like this: {id: 5, value: 'some value'}
行是对象的集合,每个对象都像这样:
{id: 5, value: 'some value'}
I have reducer, which changes the value of an object with specific id: 我有reducer,它使用特定的id更改对象的值:
case 'SET_NEW_ROW_VALUE':
let currentRows = state.rows;
const changedIndex = currentRows .findIndex((obj) => obj.id === action.id);
currentRows [changedIndex].value = action.value;
return Object.assign({}, state, {
rows: currentRows
});
Everything works, but, if state is changed, the component doesn't re-render. 一切正常,但是,如果状态发生变化,则组件不会重新渲染。 I am sure that state is changed, because I see the new state in
mapStateToProps
with console.log
, every time when it is changed, but I don't see console.log
from renderRows
. 我相信,状态改变,因为我看到了新的状态
mapStateToProps
用console.log
,每次当它被改变了,但我没有看到时间console.log
从renderRows
。
Each row component has and onHover
. 每个行组件都有and
onHover
。 If I hover the row, it is re-rendered and I see the new state for the row with the new value. 如果将鼠标悬停在该行上,则会重新渲染该行,并看到具有新值的行的新状态。
Your component is not rerendering because your object is the same as it was before 您的组件未重新渲染,因为您的对象与之前相同
In a rendering cycle, React does a diff check on the new incoming props. 在渲染周期中,React对新传入的道具进行差异检查。 If anything is different, it re-renders.
如果有任何不同,它将重新渲染。 In your case, the object is the same object as before.
在您的情况下,该对象与以前的对象相同。
As an example: 举个例子:
var rows = {id: 1, value: 'someVal'};
var oldRows = rows;
rows.id = 2;
rows.value = 'someNewVal';
console.log(rows === oldRows); // => true
React does a diff check between the rows
and the oldRows
and sees that the object itself is the same! React
rows
和oldRows
之间进行了差异检查,发现对象本身是相同的! Since the diff check sees equality, no re-rendering occurs. 由于差异检查发现相等,因此不会发生任何重新渲染。
The easiest way around this is to update prop values by their primitives within the object. 解决此问题的最简单方法是通过对象中的属性值更新属性值 。
For example this will force a rerendering cycle when a change occurs: 例如,这将在发生更改时强制重新渲染周期:
function mapStateToProps(state) {
console.log('mapState');
console.log(state.rows.rows);
return {
id: state.rows.rows.id,
value: state.rows.rows.value
}
}
If an object is absolutely necessary to be passed to your component, you can create a new object in your redux stores. 如果绝对需要将对象传递给组件,则可以在redux存储中创建一个新对象。 Something like
state.rows = Object.assign({}, oldRows)
should do the trick. 诸如
state.rows = Object.assign({}, oldRows)
应该可以解决。
in redux you should never mutate the state , so currentRows[changedIndex].value = action.value;
在redux中, 永远不要改变状态 ,所以
currentRows[changedIndex].value = action.value;
is forbidden 是禁止的
Here is a possible solution : 这是一个可能的解决方案:
case 'SET_NEW_ROW_VALUE':
const rows = state.rows.map(
(row, index) => row.id !== action.id ?
row :
{...row, value: action.value}
);
return {...state, rows};
In your solution, you don't have a new reference for the prop state.rows
after executing the case SET_NEW_ROW_VALUE
. 在您的解决方案中,执行案例
SET_NEW_ROW_VALUE
后,您没有关于prop state.rows
的新引用。 As react-redux
use shallow comparison
( ===
operator) to detect if an object has changed, with your solution the component will not be re-rendered as state.rows
will be the same object (same reference) than before 由于
react-redux
使用shallow comparison
( ===
运算符)来检测对象是否已更改,因此在您的解决方案中该组件将不会重新渲染为state.rows
将是与以前相同的对象(相同的引用)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.