You*_*oon 5 javascript reactjs immutable.js redux
似乎在将redux与react结合使用时,immutable.js几乎已成为行业标准。我的问题是,当我们使用散布运算符时,是否不是一成不变地对redux状态进行更改?例如,
const reducer = (state=initialState, action) => {
switch(action.type){
case actionType.SOME_ACTION:
return {
...state,
someState: state.someState.filter(etc=>etc)
}
}
Run Code Online (Sandbox Code Playgroud)
我用redux设置状态不是一成不变的吗?使用immutable.js OVER传播算子使对象不可变的好处是什么?
很抱歉,如果有人提出这个问题,但我找不到让我满意的答案。我了解不可变对象的好处,但不了解在点运算符上使用immutable.js库的重要性。
Ano*_*sSB 10
是! ES6传播运算符可以完全用作immutable.js的替代者,但是有一个主要警告,您必须始终保持态势感知。
您和您的其他开发人员将100%负责维护不变性,而不是让immutable.js为您处理。这是关于如何使用ES6“ spread operator”及其各种功能(例如filter和)自行管理不可变状态的详细信息map。
以下内容将探讨以不变和变异的方式将值移除和添加到数组或对象。我在每个示例中注销initialState和newState,以证明我们是否已突变initialState。这很重要的原因是,如果initialState和newState完全相同,则Redux不会指示UI重新呈现。
注意:如果您尝试使用以下任何变种的解决方案,则Immutable.js会使应用程序崩溃。
const initialState = {
members: ['Pete', 'Paul', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'REMOVE_MEMBER':
return {
...state,
members: state.members.filter(
member => member !== action.member
)
}
}
}
const newState = reducer(
initialState,
{type: 'REMOVE_MEMBER', member: 'Pete'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Pete', 'Paul', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'REMOVE_MEMBER':
state.members.forEach((member, i) => {
if (member === action.member) {
state.members.splice(i, 1)
}
})
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'REMOVE_MEMBER', member: 'Pete'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'ADD_MEMBER':
return {
...state,
members: [...state.members, action.member]
}
}
}
const newState = reducer(
initialState,
{type: 'ADD_MEMBER', member: 'Ringo'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'ADD_MEMBER':
state.members.push(action.member);
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'ADD_MEMBER', member: 'Ringo'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'Pete', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'UPDATE_MEMBER':
return {
...state,
members: state.members.map(member => member === action.member ? action.replacement : member)
}
}
}
const newState = reducer(
initialState,
{type: 'UPDATE_MEMBER', member: 'Pete', replacement: 'Ringo'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'Pete', 'George', 'John']
}
const reducer = (state, action) => {
switch(action.type){
case 'UPDATE_MEMBER':
state.members.forEach((member, i) => {
if (member === action.member) {
state.members[i] = action.replacement;
}
})
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'UPDATE_MEMBER', member: 'Pete', replacement: 'Ringo'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'Ringo']
}
const reducer = (state, action) => {
switch(action.type){
case 'MERGE_MEMBERS':
return {
...state,
members: [...state.members, ...action.members]
}
}
}
const newState = reducer(
initialState,
{type: 'MERGE_MEMBERS', members: ['George', 'John']}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: ['Paul', 'Ringo']
}
const reducer = (state, action) => {
switch(action.type){
case 'MERGE_MEMBERS':
action.members.forEach(member => state.members.push(member))
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'MERGE_MEMBERS', members: ['George', 'John']}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
对于经验丰富的开发人员而言,上述更改数组的示例似乎是显而易见的坏习惯,但对于新手来说,这是一个容易犯的错误。我们希望任何“ 变异方式”的代码片段都可以在代码审查中被发现,但事实并非总是如此。让我们来谈谈一些对象,这些对象在自己处理不可变性时比较麻烦。
const initialState = {
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
stuart: {
name: 'Stuart',
instrument: 'Bass'
}
}
}
const reducer = (state, action) => {
switch(action.type){
case 'REMOVE_MEMBER':
let { [action.member]: _, ...members } = state.members
return {
...state,
members
}
}
}
const newState = reducer(
initialState,
{type: 'REMOVE_MEMBER', member: 'stuart'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
stuart: {
name: 'Stuart',
instrument: 'Bass'
}
}
}
const reducer = (state, action) => {
switch(action.type){
case 'REMOVE_MEMBER':
delete state.members[action.member]
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'REMOVE_MEMBER', member: 'stuart'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
ringo: {
name: 'George',
instrument: 'Guitar'
}
}
}
const reducer = (state, action) => {
switch(action.type){
case 'CHANGE_INSTRUMENT':
return {
...state,
members: {
...state.members,
[action.key]: {
...state.members[action.member],
instrument: action.instrument
}
}
}
}
}
const newState = reducer(
initialState,
{type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
const initialState = {
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
ringo: {
name: 'George',
instrument: 'Guitar'
}
}
}
const reducer = (state, action) => {
switch(action.type){
case 'CHANGE_INSTRUMENT':
state.members[action.member].instrument = action.instrument
return {
...state,
members: state.members
}
}
}
const newState = reducer(
initialState,
{type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
如果您已经做到了这一点,那么恭喜!我知道这是一篇冗长的文章,但是我觉得证明没有Immutable.js来防止自己需要采取的所有Mutated方法非常重要。一个巨大的优势,使用Immutable.js,超越防止你写不好的代码,是辅助方法,如mergeDeep和updateIn
const initialState = Immutable.fromJS({
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
ringo: {
name: 'George',
instrument: 'Guitar'
}
}
})
const reducer = (state, action) => {
switch (action.type) {
case 'ADD_MEMBERS':
return state.mergeDeep({members: action.members})
}
}
const newState = reducer(
initialState,
{
type: 'ADD_MEMBERS',
members: {
george: { name: 'George', instrument: 'Guitar' },
john: { name: 'John', instrument: 'Guitar' }
}
}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>Run Code Online (Sandbox Code Playgroud)
const initialState = Immutable.fromJS({
members: {
paul: {
name: 'Paul',
instrument: 'Guitar'
},
ringo: {
name: 'George',
instrument: 'Guitar'
}
}
})
const reducer = (state, action) => {
switch (action.type) {
case 'CHANGE_INSTRUMENT':
return state.updateIn(['members', action.member, 'instrument'], instrument => action.instrument)
}
}
const newState = reducer(
initialState,
{type: 'CHANGE_INSTRUMENT', member: 'paul', instrument: 'Bass'}
);
console.log('initialState', initialState);
console.log('newState', newState);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>Run Code Online (Sandbox Code Playgroud)