在这种情况下如何重新渲染子组件?
How to re-render child component In this situation?
问题
如果我点击一个数字,数字应该会增加但不会增加。
如您所见,子组件没有重新渲染。 (如果我将 '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);
要将值增加 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);`
您需要获取 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。
您需要修改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);
稍微修改一下你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);
这是因为键可以帮助您确定该元素是否
在虚拟 Dom 中进行比较时已更改,
所以如果元素的 id 相同,
即:第一里 1,第二里 2,
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] }
}
现在密钥每次都会用值更新,但应该
不会增加,因为它将是第二个 li 的相同键
dom 会给你一个错误
所以每次 1 到 2 它的 id 都会去——即 1-1 =0
here is the working Sample
https://codesandbox.io/s/mz6zy5rq28
问题
如果我点击一个数字,数字应该会增加但不会增加。
如您所见,子组件没有重新渲染。 (如果我将 '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);
要将值增加 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);`
您需要获取 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。
您需要修改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);
稍微修改一下你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);
这是因为键可以帮助您确定该元素是否 在虚拟 Dom 中进行比较时已更改, 所以如果元素的 id 相同, 即:第一里 1,第二里 2, 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] }
}
现在密钥每次都会用值更新,但应该 不会增加,因为它将是第二个 li 的相同键 dom 会给你一个错误 所以每次 1 到 2 它的 id 都会去——即 1-1 =0
here is the working Sample
https://codesandbox.io/s/mz6zy5rq28