简体   繁体   English

更改Redux状态时,组件不会重新渲染-React

[英]Component doesn't re-render when Redux state is changed - React

I have RowsCont with renderRows 我有RowsContrenderRows

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 . 我相信,状态改变,因为我看到了新的状态mapStateToPropsconsole.log ,每次当它被改变了,但我没有看到时间console.logrenderRows

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 rowsoldRows之间进行了差异检查,发现对象本身是相同的! 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM