Best way to update linked status fields with split gears?

I am trying to develop an ideal way to update several top-level fields in my state tree, while maintaining shared reducers.

Here is a simple solution that I came up with.

var state = { fileOrder: [0], files: { 0:{ id: 0, name: 'asdf' } } }; function handleAddFile(state, action) { return {...state, ...{[action.id]:{id: action.id, name: action.name}}}; }; function addFileOrder(state, action) { return [...state, action.id]; } // Adding a file should create a new file, and add its id to the fileOrder array. function addFile(state, action) { let id = Math.max.apply(this, Object.keys(state.files)) + 1; return { ...state, fileOrder: addFileOrder(state.fileOrder, {id}), files: handleAddFile(state.files, {id, name: action.name}) }; } 

I can currently submit one action {type: ADD_FILE, fileName: 'x'} , then addFile creates an internal action to send to addFileOrder and addFile .

I am curious if this is considered the best approach to any of the below.

Instead, submit two actions: one to add the file, then enter its id and send the ADD_TO_FILE_ORDER action with the identifier. OR Fire and an action like {type: ADD_FILE, name: 'x', id: 1} , instead of allowing addFile compute a new identifier. This will allow me to use combineReducers and filter by type of action. This example is probably trivial, but my actual state tree is a bit more complex, with each file being added also need to be added to other objects.

In some additional context, a more complete state tree would look like this.

 { "fileOrder": [0] "entities": { "files": { 0: { id: 0, name: 'hand.png' } }, "animations": { 0: { id: 0, name: "Base", frames: [0] } }, "frames": { 0: { id: 0, duration: 500, fileFrames: [0] } }, "fileFrames": { 0: { id: 0, file: 0, top: 0, left: 0, visible: true } } } } 

To add a file you will need:

  • Add it to the file hash.
  • Add it to the fileOrder array.
  • Add a frame reference to the file for each of the frames.
  • Add each new file to the frame for which it was created.

The last two points make me wonder if I can even use combReducers.

+7
redux reducers
source share
2 answers

In the end, I found a fairly simple solution to this problem.

Both of these blocks from the documentation are functionally the same.

 const reducer = combineReducers({ a: doSomethingWithA, b: processB, c: c }); // This is functionally equivalent. function reducer(state, action) { return { a: doSomethingWithA(state.a, action), b: processB(state.b, action), c: c(state.c, action) }; } 

I finished setting up the second block and always walked along my global state tree. As long as nothing changes state along the way, all gearboxes work fine.

 // Simple change to pass the entire state to each reducer. // You have to be extra careful to keep state immutable here. function reducer(state, action) { return { a: doSomethingWithA(state.a, action, state), b: processB(state.b, action, state), c: c(state.c, action, state) }; } 
+7
source share

Based on the authorโ€™s decision:

I had the same problem when I needed (only a small) access outside my part of the state gearbox. I think this solution can work in practice if you try not to change anything but one value, such as a flag or counter.

This impurity can become insane if other developers are not protected from their code. Imagine what happens if the change in b and c of the state part begins, b change part of a and c, etc.

You might want to reduce the surface area of โ€‹โ€‹the impurity as follows:

 function reducer(state, action) { return { a: doSomethingWithA(state.a, action, state.globals), b: processB(state.b, action, state.globals), c: c(state.c, action, state.globals) }; } 
+2
source share

All Articles