-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
md: Readme updated, immer-reduxd file was added
- Loading branch information
DTUGYILMAZ
committed
Dec 21, 2020
1 parent
3588486
commit 39dc0ce
Showing
4 changed files
with
153 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
# SagaSplash | ||
After clone this project, run this commands in terminal | ||
``` | ||
$ cd saga-SagaSplash | ||
$ yarn | ||
$ yarn start | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
|
||
## Test redux reducers with Immer | ||
|
||
I recently started using Immer in redux reducers in my react app since I have a lot of nested states in them. (lets avoid the fact the these nesting can be solved with sub reducers). | ||
The usage of Immer is clear for me, but once I started to write unit tests with jest I started wondering, that should I avoid using Immer in the tests ? | ||
Lets have a basic reducer example: | ||
``` | ||
export default function (state = initialState, action) { | ||
return produce(state, (draftState) => { | ||
switch (action.type) { | ||
case MY_TYPE: | ||
draftState.some.nested.flag = true; | ||
break; | ||
} | ||
}); | ||
} | ||
``` | ||
then my test which also using Immer | ||
``` | ||
it('should handle MY_TYPE', () => { | ||
const storeState = reducer(initialState, { | ||
type: MY_TYPE | ||
}); | ||
const newState = produce(initialState, (draftState) => { | ||
draftState.some.nested.flag = true; | ||
}); | ||
expect(storeState).toEqual(newState); | ||
}); | ||
``` | ||
So my question is that should I avoid using Immer produce in the tests and make the copy of the nested object manually with the spread syntax ? Something like: | ||
``` | ||
.toEqual({ | ||
...initialState, | ||
some: { | ||
...initialState.some, | ||
nested: { | ||
...initialState.some.nested, | ||
flag: true | ||
} | ||
} | ||
}) | ||
``` | ||
So is there any pitfalls using Immer in tests ? | ||
|
||
In this case Immer does not change all the state.For example: | ||
``` | ||
const state = { | ||
some: { | ||
another: {}, | ||
nested: { | ||
flag: true | ||
} | ||
} | ||
}; | ||
const nextState1 = produce(state, draft => { | ||
draft.some.nested.flag = false; | ||
}); | ||
const nextState2 = produce(state, draft => { | ||
draft.some.nested.flag = false; | ||
}); | ||
expect(nextState1).toEqual(nextState2); | ||
expect(nextState1.another).toBe(nextState2.another); // true! | ||
expect(nextState1).toBe(nextState2); // false | ||
expect(nextState1.some).toBe(nextState2.some); // false | ||
expect(nextState1.some.nested).toBe(nextState2.some.nested); // false | ||
``` | ||
Where "toBe" is a function which check identity of object instances(unlike "toEqual").I think, you should not avoid using Immer in the unit tests.Probably it requires another assert function which checks that only part of tree is changed. | ||
|
||
Access vue method within vuex mapState | ||
|
||
I have an important task to do while data is computed within a vuex mapState.I need to call this vue method countAlerts every time data is changed; to do that the computed property needs to call that method but this scope has no vue methods when it is used insight vuex mapState. | ||
``` | ||
export default { | ||
name: "Alerts", | ||
methods: { | ||
countAlerts(data, period) { | ||
/// DO SOMETHING, THEN RETURN DATA | ||
return data; | ||
} | ||
}, | ||
computed: { | ||
...mapState({ | ||
foundation: state => state.insights.foundation, | ||
insights: state => { | ||
return state.insights.list.filter(al => { | ||
switch (state.insights.foundation.period) { | ||
case "daily": | ||
// ====>> NEED TO CALL METHOD HERE <<===== | ||
al = this.countAlerts(al, "daily"); | ||
if ( | ||
al.threeDayUp || | ||
al.threeDayDown || | ||
al.greatDayUp || | ||
al.greatDayDown | ||
) { | ||
return al; | ||
} | ||
break; | ||
/// MORE CODE ABOVE | ||
} | ||
}); | ||
} | ||
}) | ||
} | ||
}; | ||
``` | ||
|
||
this is bound to the component's contex when you define computed props as functions. | ||
From the docs: | ||
``` | ||
// to access local state with `this`, a normal function must be used | ||
countPlusLocalState(state) { | ||
return state.count + this.localCount | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,34 @@ | ||
{ | ||
"name": "saga-splash", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"react": "^16.12.0", | ||
"react-dom": "^16.12.0", | ||
"react-redux": "^7.2.1", | ||
"react-scripts": "^3.4.1", | ||
"redux": "^4.0.5", | ||
"redux-saga": "^1.1.3" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test --env=jsdom", | ||
"eject": "react-scripts eject" | ||
}, | ||
"devDependencies": { | ||
"prettier": "^1.14.0" | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
} | ||
"name": "saga-splash", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"react": "^16.12.0", | ||
"react-dom": "^16.12.0", | ||
"react-redux": "^7.2.1", | ||
"react-scripts": "^3.4.1", | ||
"redux": "^4.0.5", | ||
"redux-saga": "^1.1.3" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"test": "react-scripts test --env=jsdom", | ||
"eject": "react-scripts eject" | ||
}, | ||
"devDependencies": { | ||
"prettier": "^1.14.0" | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
} | ||
} |