I have gone through the definitions of the Pure and Impure Javascript functions in the ReactJs Official Docs.
Pure functions are ones that do not attempt to change their inputs, and always return the same result for the same inputs.
Example
function sum(a, b) {
return a + b;
}
Impure function is one that changes its own input.
Example
function withdraw(account, amount) {
account.total -= amount;
}
Now, can somebody tell me, how can I mistakenly make functions impure in React/Redux, where pure functions are required?
React and Redux
both need pure functions coupled with immutability to run in a predictable fashion.
If you don't follow these two things, your app will have bugs, the most common being React/Redux
not able to track changes and unable to re-render when your state/prop
changes.
let state = {
add: 0,
}
function render() {
//...
}
//pure function
function effects(state,action) {
//following immutability while updating state, not directly mutating the state.
if(action == 'addTen') {
return {...state, add: state.add + 10}
}
return state;
}
function shouldUpdate(s) {
if(s === state){
return false
}
return true
}
state = effects(state, 'addTen')if(shouldUpdate(state)) {
render();
}
The state is held by the state object which has only added property. This app renders the app property. It shouldn't always render the state when anything happens but should check whether a change occurred in the state object.
Like so, we have an effects function, a pure function
which we use to affect our state. You see that it returns a new state when the state is to be changed and returns the same state when no modification is required.
We also have a shouldUpdate
function which checks using the === operator whether the old state and the new state is the same.
To make mistakes in terms of React, you can actually do the following :
function effects(state,action) {
doRandom(); // effects should only be called for updating state.
// Doing any other stuff here would make effects impure.
if(action == 'addTen') {
return {...state, add: state.add + 10}
}
return state;
}
You can also make mistakes by setting the state directly and not using effects
function.
function doMistake(newValue) {
this.state = newValue
}
The above should not be done and only effects
function should be used to update the state.
In terms of React, we call effects
as setState
.
combineReducers
utility checks for reference changes.connect
method generates components that check reference changes for both the root state and the return values from mapState
functions to see if the wrapped component actually needs to re-render.pure functions
with no side effects so that you can correctly jump between different states.You can easily violate the above three by using impure functions as reducers.
Following is taken directly from redux docs:
It's called a reducer because it's the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue)
.
It's very important that the reducer stays pure. Things you should never do inside a reducer:
Mutate its arguments;
Perform side effects like API calls and routing transitions;
Call non-pure functions, e.g. Date.now() or Math.random().
Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.
Simply said the state cannot be mutated. A new instance of the state should be returned every time there is a change so
This code is not correct :
const initialStates = {
items: ['item1']
}
export const ItemMaster = (state = initialStates, action) => {
switch (action.type) {
case TYPES.ADD_ITEM:
{
state.items.push(action.item)
return state
}
default:
return state
}
}
This code when written as a pure function below, This returns a new instance of the array it does not modify the actual array itself. This is the reason you should use a library like immer to handle immutability
const initialStates = {
items: ['item1']
}
export const ItemMaster = (state = initialStates, action) => {
switch (action.type) {
case TYPES.ADD_ITEM:
{
state = {...state,items:state.items.concat(action.item)}
return state
}
default:
return state
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With