问题
Now if i want to change value in store i should do following steps:
- Go to constants/actionTypes file, create a line with action type
- Go to actions and create action function
- In each component where i use it i should create a function for mapDispatchToProps
- In reducer i should write a logic of changing
Whats the point of such complexity? Will it be wrong if i will do just one file with actions which will change the state? For example:
// actions.js
export const setCategories = (payload, setState, currentState) => setState({ categories: payload })
export const addCategory = (payload, setState, currentState) => setState({ categories: [...currentState.category, payload] })
To make it work i can create just couple of universal functions for all projects
1) getActions, which authomaticly collects all exports from actions.js and provide them to mapDispatchToProps, so in all components we could just write
const mapDispatchToProps = getActions
code of it can be something like
// actionsDispatcher.js
import * as actions from 'actions'
const getActions = (dispatch, ownProps) => {
Object.keys(actions).forEach(actionName => {
const fn = actions[actionName]
actions[actionName] = payload => dispatch({ action: fn, payload, type: _.toSnakeCase(actionName) })
}
return actions
}
which means we pass to dispatch the function of action from actions.js
2) setState which will work similary to react function, but for redux state
then in reducer function we just right
function rootReducer(state = initialState, action) {
if (action.action) {
action.action(action.payload, setState, state)
}
// here we make it extandable for ordinary way if required
if (action.type === '...') {
// ...
}
}
and nothing else...
So the question is whats wrong in such approach that will require for coder just write a function in one file 'actions.js' and call it from any component as props.someActionName(someParams) instead of changing 4 differents files?
Thank you
回答1:
Redux is supposed to make complex requirements easier to implement but if you have simple requirements then it makes implementing these requirements more complicated.
The motivation mentions CQRS(Command Query Responsibility Segregation) that separates how you read from store (in redux with selectors and I'm a big fan of reselect) with how you write to it (with action and reducers).
The actions and reducers are the command (write) part of CQRS and is event sourcing, redux is sometimes referred to as an event store. This enables you to add or remove handlers (reducers or middle ware) for your events (actions) that can update the store, dispatch other events (=actions), do asynchronous stuff, write to local storage.
If you need to do all these things in one function (async fetch, write to local storage, call other functions (dispatch other actions),...) then that function becomes unmanageable.
Even if the function only calls other functions then it still needs to know the entire process of certain action. But if (for example) you had a local storage middleware that would write to storage on certain actions then no other code needs to know how or when it's called. So when logic of writing to local storage changes it is limited to the local storage middle ware.
This is the advantage of handlers (reducers, middleware) listening to events (actions), the handler only needs to know about a small portion of the process, not the entire process.
With event resourcing we also know why the state has a certain value instead of only knowing what the state is, the article states:
However there are times when we don't just want to see where we are, we also want to know how we got there.
Another big advantage of an event store is that you can re create the data by playing back the events. All this is excellently done with redux def tools.
Here is a great book on React with Redux.
回答2:
Conventional-redux is a:
Library for small and medium react applications, it wraps the react-redux and provides API based on convention over configuration pattern without breaking redux compatibility.
You simply define an interactor:
class CounterInteractor {
// initial state
defaultState() {
return 0;
}
// actions:
doubleAsync() {
setTimeout(() => { this.dispatch('counter:double') }, 500)
}
// reduce methods:
onIncrement() {
return this.state + 1;
}
onDouble() {
return this.state * 2;
}
}
And dispatch actions to that interactor from your connected component component. That's it!
来源:https://stackoverflow.com/questions/61556343/what-is-the-meaning-of-actions-and-action-types-in-react-redux