The introduction
In daily use redux, when the view from an action request and corresponding reducer processing, sometimes store in the corresponding state values have changed, but not in view, enters the life cycle of componentWillReceiveProps. This paper mainly explains what causes this phenomenon.
Value reference
Simple values (scalar primitives) that contain data types such as NULL,undefined, string, number, Boolean, and SYMBOL in ES6.
example
const a = 1;
let b = a;
b === a // true
Copy the code
Features: When the assigned variable changes, the value of the assigned variable does not change
const nickname = 'ssx';
let lastname = nickname;
lastname === nickname // true;
lastname = 'Mr.oldwang';
nickname //'ssx'
Copy the code
Refer to the assignment
For composite objects (arrays, objects, functions)
example
- object
const user1 = { nickname: 'ssx', age: 23 }
let user2 = user1;
user2; // { nickname: 'ssx', age: 23 }
user1 === user 2; // true
user2.nickname = 'gdd';
user1.nickname = 'gdd';
Copy the code
- An array of
Const userIdlist = [1, 2, 3, 4];let newUserIdlist = userIdlist;
newUserIdlist === userIdlist; // falsenewUserIdlist[0] = 2; newUserIdlist; / / (2, 2, 3, 4] userIdlist; / / (2, 2, 3, 4]Copy the code
If the data structure follows the project, the complexity increases. Reference assignments can cause the desired effect to be inconsistent with the actual one.
Talk about the problems with reference assignment for actual React projects
1. The listening method of redux is not triggered, so mapStateToProps is not executed, and the view is not refreshed. Undispatch an action that has already modified the value in the corresponding store due to an improper reference assignmentCopy the code
Write some practical examples according to the questions
For example 1
// info = {id: 10023, nickname: 'ssx_real', age: 40}
function userlistReducer(
state = [ {id: 10023, nickname: 'ssx', age: 23} ],
action ={}
) {
const { type, info } = action;
case "GET_USERINFO_LOADING":
return state;
case "GETREAL_USERINFO_SUCCESS":
{
const userlist = state;
const fakeUserinfo = userlist.find(u => u.id === info.id);
if (fakeUserinfo) {
fakeUserinfo.nickname = info.nickname;
fakeUserinfo.age = info.age;
}
return [...userlist];
}
case. // other omit default:return state;
}
Copy the code
The result is that we want to change the original fake data to the real data obtained through the network, but the value of the target object has been changed before the return. Even if the corresponding value in the store has been changed after dispatch, it is not the desired effect.
prevprops userlist: [{id: 10023, nickname: 'ssx_real', age: 40}]
action: GETREAL_USERINFO_SUCCESS
nextprops userlist: [{id: 10023, nickname: 'ssx_real', age: 40}]
Copy the code
rewrite
// realInfo = {id: 10023, nickname: 'ssx_real', age: 40}
function userlistReducer(
state = [ {id: 10023, nickname: 'ssx', age: 23} ],
action ={}
) {
const { type, realInfo } = action;
case "GET_USERINFO_LOADING":
return state;
case "GETREAL_USERINFO_SUCCESS": { const userlist = state; const fakeUserinfo = {... userlist.find(u => u.id === realInfo.id)};if (fakeUserinfo) {
fakeUserinfo.nickname = realInfo.nickname;
fakeUserinfo.age = realInfo.age;
}
return [
...userlist.filter(u => u.id !== realInfo.id),
...[fakeUserinfo]
]
}
case. // other omit default:return state;
}
Copy the code
For the example in 2
componentWillReceiveProps(nextProps) {
// todo something...
for (let item of newProps.groupRooms[this.state.roomID]) {
let item = {};
item.obj = item
item.obj.lastRecord = nextProps.chatData.chatlist.lastRecord
roomsData.push(item);
}
this.setState({ roomsData });
// todo something...
}
Copy the code
The above example did not intend to change the value of the corresponding groupRooms[this.state.roomid] but changed its value indirectly by using a reference assignment. This is the case in step 2 above, where an action changes the value in the corresponding store without dispatch.
rewrite
componentWillReceiveProps(nextProps) {
// todo something...
for (let item of newProps.groupRooms[this.state.roomID]) {
letitem = {}; item.obj = {... item}; item.obj.lastRecord = {... nextProps.chatData.chatlist.lastRecord} roomsData.push(item); } this.setState({ roomsData }); // todo something... }Copy the code
Some ways to resolve reference assignment based on different data types:
- Es6 extension operator
.
- An array of
concat()
[...arr1,...arr2]
arr1 = new Array(... arr2)
- object
Object.assign({}, obj1)
obj2 = {... obj1}
map
A collection ofm1 = new Map() m2.forEach((v,k) => m1.set(k, v))
These methods mainly perform a shallow copy. When the key of an object is copied, the object referenced by the key will not be copied
The tail language
If you have problems with reference assignments in your projects, hopefully this article will helpCopy the code