The basics:
If you want to start using redux with asyncronous code (eg ajax requests) then you’ll need to use another tool:
If you are using Typescript then this is useful: https://redux.js.org/recipes/usage-with-typescript
There are a few concepts that are super important
Lets say you are making a TODO application. This application has a beautiful frontend that automatically renders your todo items from a datastructure. Something like this:
const store = {
todos : [
{title: "get groceries", done: false},
{title: "call mom", done: true},
{title: "learn Redux", done: false},
{title: "walk dog", done: false},
]
}
In redux, the store is immutable. We’ll see what that implies when we talk about reducers a little later.
Tools like React make it easy to take an application state and turn it into widgets but we wont get into that just yet. You can do this with pure vanilla JavaScript by looping over our todos and simply appending DOM elements.
An action is also a JSON object. Here are some examples:
{type: "ADD_TODO", title: "pay rent"}
{type: "DELETE_TODO", index: 2}
{type: "SET_DONE", index: 1, done: true}
{type: "SET_DONE", index: 1, done: false}
Given the example “store” we set up above can you see what effects these actions should have? What does it look like we are trying to do here?
Now there is some weird language around this. If you want Redux to execute an action then you dispatch the action. Then Redux should update the store through use of a reducer (we’ll get to those soon).
So if we wanted Redux to actually add a thing to our todo list we would do something like:
dispatch({type: "ADD_TODO", title: "pay rent"})
This is kinda a pain to write out so usually instead of doing thigs like this we make use of action creators. Eg:
const ADD_TODO = "ADD_TODO"
function addTodo(title){ //action creator
// validation maybe
return {type: ADD_TODO, title: title}
}
dispatch(addTodo("learn redux"))
Reducers are the things that execute actions on the state. Here is an example following from the above:
const initialState = { // note the use of const. This is immutable
todos : [1,2,3],
stuff : "things"
}
function theReducer(state = initialState, action){
// {type: ADD_TODO, title: "buy hats"}
switch(action.type){
case ADD_TODO:
return {
...state, // we copy all the things using some ES6 syntax
todos: [...state.todos, {title: action.title, done:false }]
}
// {
// todos : [1,2,3,{type: ADD_TODO, title: "buy hats"}],
// stuff : "things"
//}
case DELETE_TODO:
return { stuff }
case SET_DONE:
return { otherStuff }
default:
// nothing changes
return state
}
}
KISS == Keep It Simple, Stupid - wikipedia
This does seem like a complicated way to do a simple thing…
Here are some benefits:
Look up the “Command Pattern” . Redux isn’t the same but it’s super powers are very similar. Therefore there are similar applications.
Redux is mostly used in the context of React. It is used for frontend development. But there is so much more it could do.
Redux is very flexible when it comes to the shape of the objects stored in the store. Flexibility is great, but it does have a downside. Basically you need to be careful about how to structure your storage, otherwise redux can run quite slow and your reducers can get very complicated.
Basically the thing to keep in mind is:
Flat is better than nested
Ok, what does that mean?
A nested data structure is something with many levels.
Let’s say we have an application that manages…agile cards one a board. Tose cards can be associated with other data structures such as repositories and reviews.
Say we store a list of cards that look like this:
{ ...
cards: [
{
"id": 123,
repository: {"id":667,"owner":"Wordz278","fullName":"Wordz278/person","sshUrl":"git@github.com:Wordz278/person.git","createdAt":"2020-02-11T12:23:43Z","private":false,"archived":false,"user":null}",
"reviews" : [
{id:}
]
}
]}