如果我点击一个数字,数字应该增加但不会增加。
如您所见,子组件不会重新渲染。 (如果我将' li'元素的键更改为Math.random(),它可以正常工作。)
我该如何解决这种情况?
一个例子发布在https://codesandbox.io/s/p5q30rxk47
上感谢阅读。
源代码大致如下。
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Parent from './Parent';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './redux';
const body = document.querySelector('body'),
store = createStore(reducer);
ReactDOM.render(<Provider store={store}><Parent/></Provider>, body);
Parent.js
import React from 'react';
import { connect } from 'react-redux';
import Child from './Child';
class Parent extends React.PureComponent {
get_numbers () {
return this.props.numbers.map((number) => (
<li key={number.id}>
<span>number : </span><br/>
<Child number={number} />
</li>
));
}
render () {
return (
<ul>
{this.get_numbers()}
</ul>
);
}
}
function mapStateToProps(state) {
return { numbers: state.numbers };
}
Parent = connect(mapStateToProps)(Parent);
export default Parent;
Child.js
import React from 'react';
import { connect } from 'react-redux';
import { increase_number } from './redux';
class Child extends React.PureComponent {
render() {
return (
<span onClick={() => this.props.increase_number(this.props.number)}>{this.props.number.value}</span>
);
}
}
function mapDispatchToProps(dispatch) {
return {
increase_number: (number) => dispatch(increase_number({ number }))
};
}
Child = connect(undefined, mapDispatchToProps)(Child);
export default Child;
redux.js
import { createAction, handleActions } from 'redux-actions';
export const increase_number = createAction('increase_number');
const initial_state = {
numbers: [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 }
]
};
export default handleActions({
increase_number: (state, action) => {
// console.log(action.payload.number.value);
action.payload.number.value++;
// console.log(action.payload.number.value);
return { ...state, numbers: [...state.numbers] }
}
}, initial_state);
答案 0 :(得分:3)
这是因为键可以帮助您确定该元素 在虚拟Dom中进行比较时发生了变化, 所以如果元素的id相同, 即:1表示第一个li,2表示第二个li, 自元素更新以来,dom永远不会知道 基于虚拟dom的变化,即使是值 正在改变 可能的解决方案可能是使用不同于1,2,3的id并更新id和值,以便Dom能够找出变化。
一个可能的黑客可能是
increase_number: (state, action) => {
//console.log(action.payload.number.value);
action.payload.number.value++;
action.payload.number.id--;
//console.log(action.payload.number.value);
return { ...state, numbers: [...state.numbers] }
}
现在密钥会随时更新值,但应该更新 不会增加,因为它将是第二李的同一把钥匙 而dom会给你一个错误 所以每次1到2时它的id都会去 - 即1-1 = 0
here is the working Sample
https://codesandbox.io/s/mz6zy5rq28
答案 1 :(得分:2)
您需要获取numbers
数组的深层副本,然后增加payload
中传递的数字的值,如下所示:
export default handleActions({
increase_number: (state, action) => {
let numberToModify = action.payload.number;
// make a new array with new objects
let newNumbers = state.numbers.map(n => ({ id: n.id, value: n.value }));
// find the one that needs to be modified
let existingNumber = newNumbers.find((number) => (number.id === numberToModify.id));
if (existingNumber) {
existingNumber.value++;
}
return { ...state, numbers: newNumbers };
}
}, initial_state);
制作了一个实例here。
答案 2 :(得分:1)
您需要修改handleAction,如下所示
export default handleActions({
increase_number: (state, action) => {
action.payload.number.value++
const currentNum = action.payload.number;
let newLst = state.numbers.map((num) => {
return num.id === currentNum.id ? {...action.payload.number} : num
})
return { ...state, numbers: newLst }
}
}, initial_state);
答案 3 :(得分:1)
略微修改了你handleActions
export default handleActions({
increase_number: (state, action) => {
action.payload.number.value++;
const currNumber = action.payload.number;
const numbers = state.numbers.map((num) => {
return num.id === currNumber.id ? { ...action.payload.number } : num
});
return { ...state, numbers }
}
}, initial_state);
答案 4 :(得分:0)
要将值增加1,您应该在redux.js文件中进行更改,如下所示:
import { createAction, handleActions } from 'redux-actions';
export const increase_number = createAction('increase_number');
const initial_state = {
numbers: [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 }
]
};
export default handleActions({
increase_number: (state, action) => {
console.log(action.payload.number.value);
// action.payload.numbers.value++;
const numbers = [...state.numbers];
numbers.push({
id: action.payload.number.value++,
value: action.payload.number.value++
})
// console.log(action.payload.number.value);
return { ...state, numbers: numbers }
}
}, initial_state);`