Redux Action Creator
Actions are just Plain Old JavaScript Objects (POJOs), We will discuss about properties of actions, and how to implement a function to create actions.
What is the Actions
The purpose of the dispatching actions to our store to desirable changes to update our states. In this way, actions almost feel like the request object or the parameters hash that you would see in a web application like Ruby on Rails.
As you remember in Rails, user just clicked a link to have access to controller. They can make changes from controller. But in Redux user may just click the button then button dispatches an action and reducer get info from action and update to state. We could see a history of every action that was passed to the reducer, making our debugging job easier.
An Action dispatching to our reducer. It’s sending an action object to reducer. Reducer is responsible for takes action object and decides based on the way how I set up my reducer. In reducer decides what I want to update about my current store.
Then reducer will return a new version of that store each time when I update data in our store. This is the reason why I had to pass reducer as argument in Index.js file. It’s giving direction to my store when I dispatched anytime. I want that action object to send to this reducer and updated my store(value of the store). Action creators are exactly that — functions that create actions. It’s easy to conflate the terms “action” and “action creator”. In Redux, action creators simply return an action:
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
This makes them portable and easy to test.
In traditional Flux, action creators often trigger a dispatch when invoked, like so:
function addTodoWithDispatch(text) {const action = {type: ADD_TODO,text}dispatch(action)}
In Redux this is not the case. Instead, to actually initiate a dispatch, pass the result to the dispatch()
function:
dispatch(addTodo(text))
dispatch(completeTodo(index))
Alternatively, you can create a bound action creator that automatically dispatches:
const boundAddTodo = text => dispatch(addTodo(text))
const boundCompleteTodo = index => dispatch(completeTodo(index))
The dispatch()
function can be accessed directly from the store as store.dispatch()
, but more likely you'll access it using a helper like react-redux's connect()
. You can use bindActionCreators()
to automatically bind many action creators to a dispatch()
function.
index.js
const store = createStore(playerReducer,composeEnchancers(applyMiddleware(thunk)))
Action creator incorporate a fetch request or any sort of async request returns just regular JavaScript objects. † The “vanilla” store implementation you get by calling [`createStore`](/api/createstore) only supports plain object actions and hands them immediately to the reducer.
However, If you wrap createStore
with applyMiddleware
, the middleware can interpret actions differently, and provide support for dispatching async actions. Async actions are usually asynchronous primitives like Promises, Observables, or thunks. When the action creator returns data like in fetchPlayer then its automatically dispatches the data in the action and sends to reducer.
Let break down each line of codes and try to understand the logic behind it.
PlayerReducer.jsexport default function playerReducer(state = {players: []}, action ) {
switch (action.type){
case 'FETCH_PLAYERS':
return {players: action.payload}case 'ADD_PLAYER':
#We need another case to add playerreturn{...state, players: [...state.players, action.payload]}case 'ADD_CONTRACT':
return {...state, newContract:action.payload}case'DELETE_CONTRACT':
return {...state, newContract:action.payload.contract}
default:
return state
}
}
Returning object with key value
I want to return an object which the key value pair of players points to an array. I am saying return an object remember what ever I returned from reducer is my new our REDUX STATE. This will be our state that I have access in any other component. Its returning a new version of state so what I am saying right now is no longer want players point to an empty array I wanted to point to the array of data that came back from my fetch request.
Adding new object
I have to hit every single player thats already in my current state and I also want to add a new one -> return{…state, players: […state.players, action.payload]}. It’s always good to have …state (spread operator) our state has a bunch of key with a bunch of value in this case. I would be fine with one spread operator but if I want to add more key and value in our state I could lose my original state. Its always good to have to two spread operators for future but what I am saying players points an array has all previous player in it with this new player (action.payload). We don’t mutate current state here just copying of the current state keys and values what we have already in the state, replace the entire object it’s not modifying state. Its says give me all the properties and values from current state and overwriting what we want and update the our store. We don’t not overwrite in current state just returning new state with new value. We always need a default : return state its self. Thats the state is coming from initial state. It’s says if the
state goes to “ADD_PLAYER” function use the state and update for our store, if not return default state which is set up in initial state.
Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using store.dispatch()
. Actions are plain JavaScript objects. Actions must have a type
property that indicates the type of action being performed. Types should typically be defined as string constants. Once your app is large enough, you may want to move them into a separate module.
Fetching request is taking sometime, I can’t return action right away and I don’t want our connect function automatically calls dispatch for us. Instead. I want to use fetch inside in our action.Then I can call dispatch once when I’ve that in thunk. It’s allows us to use dispatch inside of fetchPlayer.js. We can’t use dispatch without thunk in action creator(fetchPlayers). We have to implement return dispatch to use instead of logging in.