Redux

Why should we avoid mutations in redux?

  • Working with immutable data structures can have a positive impact on performance, if done right. In the case of React, performance often is about avoiding unnecessary re-rendering of your app, if the data did not change.
  • To achieve that, you need to compare the next state of your app with the current state. If the states differ: re-render. Otherwise don't.
  • To compare states, you need to compare the objects in the state for equality. In plain old JavaScript objects, you would need to deep compare in order to see if any property inside the objects changed.

In terms of react, you could use it for the shouldComponentUpdate method, like the popular PureRenderMixin does.
  • shouldComponentUpdate(nextProps, nextState) {
        return nextState !== this.state;
    }
    
    This function prevents re-rendering, when the state did not change.
  • There are several reasons why immutable state is chosen over the mutable one.
  •  mutation tracking is pretty difficult. For example when you are using a variable in several pieces of code and the variable can be modified in each of this places, you need to handle each change and synchronize results of mutation. This aproach in many cases leads to bidirectional data flows. Pieces of data are flowing up and down across the functions, variables and so on. Code starts beeing polluted by if-else constructions that are oly responsible for handling state changes. When you add some asynchronous calls your state changes can be even harder to track. Of course we can subscribe to data events (for example Object.observe), but it can lead to situation that some part of application that missed change stays out of sync with other part of your program.
    Immutable state helps you to implement unidirectional data flow that helps you to handle all changes. First of all data flows from top to bottom. That means all changes that were applied to the main model are pushed to the lower components. You can always be sure that the state is the same in all places of the application, because it can be changed only from one place in the code - reducers. There is also one thing worth of mentioning - you can reuse data in several components. State cannot be changed (a new one can be created), so it's pretty safe to use same piece of data in several places.
    You can find more information about pros and cons of mutability (and about the reason why it was chosen as a main approach of Redux) here:

Avoiding array and object mutations:




For updating nested properties:
https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns


var persons = [
  {
    name: "name1",
    isGraduated: true
  },
  {
    name: "name2",
    isGraduated: false
  },
  {
    name: "name3",
    isGraduated: false
  },
];
var newPerson = {
  name: "name4",
  isGraduated: false
}
function updatePersons(newObj) {
 //Avoiding Array mutations
 //return persons.concat(newObj);//ES5
  return [
    ...persons,
    newObj
  ]//ES6
  
  //Array mutations which we shouldn't prefer
  //return persons.push(newObj);
  
}

var PersonsafterAdding = updatePersons(newPerson);
console.log(`AfterAdding: 
 ${JSON.stringify(PersonsafterAdding)}`);
console.log(`personsAfterAdding: 
 ${JSON.stringify(persons)}`);

function deletePerson(index) {
 //Avoiding array mutations
   //ES5
  /*    return [
       persons.slice(0, index).concat(persons.slice(index+1))
     ]  */
    //ES6
     return [
      ...persons.slice(0, index),
      ...persons.slice(index+1)
     ]
  //Array mutation which we shouldn't prefer
  //return persons.splice(index, 1);
}
var afterDelete = deletePerson(1);
console.log(`afterDelete: 
 ${JSON.stringify(afterDelete)}`);
console.log(`personsAfterDelete: 
 ${JSON.stringify(persons)}`);

var afterEdit = editPersons(1);
function editPersons(id) {
 //Avoiding array mutations   
    //ES6
   return persons.map((person, index) => {
   //ES6
    //return (index === id) ? {...person, isGraduated: true, newProp: true} : person;
    
    //ES5
    /* if(index === id) {
      person = {
        isGraduated: true,
        newProp: true
      }
    }
    return person; */
    /* OR
    return Object.assign({}, person, {isGraduated: !person.isGraduated, newProp: true}; */
    
    //Array mutations
    //return persons.splice(id, 1, {name: person.name, isGraduated: !person.isGraduated, newProp: true});
   });
}

console.log(`afterEdit: 
 ${JSON.stringify(afterEdit)}`);
console.log(`personsAfterEdit: 
 ${JSON.stringify(persons)}`);


Concurrency vs Parallelism:

Concurrency is two lines of customers ordering from a single cashier (lines take turns ordering); Parallelism is two lines of customers ordering from two cashiers (each line gets its own cashier)

State management in Reactjs:





The key of the "no-mutations" mantra is that if you can not mutate the object, you are forced to create a new one (with the properties of the original object plus the new ones).

To update the components when an action is dispatched, Redux connector checks if the object is different, not if the properties have changed (which is a lot faster), so:

  • If you create a new object, Redux will see that the object is not the same, so it will trigger the components updates.
  • If you mutate the objet that it is already in the store (adding or changing a property, for example) Redux will not see the change, so it will not update the components.
  • Redux checks if the old object is the same as the new object by comparing the memory locations of the two objects. If you mutate the old object’s property inside a reducer, the “new state” and the “old state” will both point to the same object and Redux will infer that nothing has changed.

  • mutation: modifying existing object/array values

    • Mutation causes bugs, such as the UI not updating properly to show the latest values
    • Mutation makes it harder to understand why and how the state has been updated











When should I use Redux?

  • Redux is a pattern for managing application state.
  • If you do not have problems with state management, you might find the benefits of Redux harder to understand.
  • Some UI libraries (like React) have their own state management system.
  • If your application becomes so complex that you are confused about where state is stored or how state changes, then it is a good time to learn Redux.

  • Redux helps us to know when did a certain slice of state change, and where did the data come from?", with predictable behavior
  • It's useful in cases when
    • You have large amounts of application state that are needed in many places in the app
    • The app state is updated frequently
    • The logic to update that state may be complex
    • The app has a medium or large-sized codebase, and might be worked on by many people
    • You need to see how that state is being updated over time

Some common rules of thumb for determining what kind of data should be put into Redux:

  1. Do other parts of the application care about this data?
  2. Do you need to be able to create further derived data based on this original data?
  3. Is the same data being used to drive multiple components?
  4. Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
  5. Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
  6. Do you want to keep this data consistent while hot-reloading UI components (which may lose their internal state when swapped)?


Redux vs Context

useReducer plus useContext together kind of make up a state management system. And that one is more equivalent to what Redux does with React, but Context by itself is not a state management system.

https://codesandbox.io/s/lurh9?file=/src/index.js

https://codesandbox.io/s/cool-butterfly-mk0mi?file=/src/index.js

Can Redux only be used with React?

What is redux library?
  • Definition from the documentation: Redux is a predictable state container for js apps
    • It's for js apps: Redux is not tied to react. react n redux are not tightly coupled. Most popular with React. but can be used with any library/ framework(Angular, Vue, Vanilla JS etc., Doesn't depend on the user interface we use)
    • It's state container
      • redux stores the state of our app
      • Whats is state of an application?
        • consider react app - 
    • It's predictable








No comments:

Post a Comment