DEV Community

Reked37
Reked37

Posted on

Intro To Redux

Redux is a Javascript library that helps manage the state and passes the correct information to the right component that needs the information. Without Redux, React has to pass the information down to its children's components in order for them to use the data. This can get tedious if the component manipulates data because you must pass down a callback function as a prop. With Redux, you are able to access the state whenever in the program.

To get started with Redux, there are three key points when setting up Redux. The first point is fairly simple, but that is naming your type of action as a variable so that when the variable is called on, Redux will use that variable to decide on what action will be used. For my project, I built a football website, and this is an example of all my player and fetch request types.

export const FETCH_PLAYERS_REQUEST = 'FETCH_PLAYERS_REQUEST'
export const FETCH_PLAYERS_SUCCESS = 'FETCH_PLAYERS_SUCCESS'
export const FETCH_PLAYERS_FAILURE = 'FETCH_PLAYERS_FAILURE'
export const DELETE_PLAYER='DELETE_PLAYER'
export const UPDATE_PLAYER='UPDATE_PLAYER'
export const POST_PLAYER='POST_PLAYER'
Enter fullscreen mode Exit fullscreen mode

Next is connecting each type with its specific action. To define an action, you must create a function that returns a Javascript object that accepts type as its first key and value by what type you want it to be connected to. The second key is called payload, which holds the values you are trying to manipulate or pass on. If the program is trying to add a new player to the data, then we would use POST_PLAYER type inside the post-player function we create and put the newPlayer as the payload. The code would look something like this.

export const postPlayer=(newPlayer)=>{
    return{
        type:POST_PLAYER,
        payload:newPlayer
    }
}
Enter fullscreen mode Exit fullscreen mode

Lastly, the most complicated out of the three parts is the reducer. The reducer starts with an initial state variable, which is a javascript object that has three keys: response, data, and errors. The initial state would look like this, where the data key is replaced by the name of the data you are going to set it to. Since I'm fetching the players of the football league, I set the key to be leaguePlayers.

const initialState={
    loading: false,
    leaguePlayers: [],
    error:''
}
Enter fullscreen mode Exit fullscreen mode

Next is defining the function of the reducer, which checks the type of the action and tries to find the type that matches its correct condition using a switch statement. The function will take two arguments: the state and the action. When the reducer is initialized, it will look through the switch statement until it comes across the correct type. After the condition has been found, we then perform the correct actions on the data type. Below is what my reducer looks like for my player data as I have it set up to fetch the data from an API, along with delete, post, and update.

const playerReducer =(state=initialState, action)=>{
    switch(action.type){
        case FETCH_PLAYERS_REQUEST: return{
            ...state,
            loading: true
        }
        case FETCH_PLAYERS_SUCCESS: return{
            loading: false,
            leaguePlayers: action.payload,
            error: ''
        } 
        case FETCH_PLAYERS_FAILURE: return{
            loading: false,
            leaguePlayers: [],
            error: action.payload
        }
        case DELETE_PLAYER:return{
            ...state,
            leaguePlayers: state.leaguePlayers.filter((player)=>{
                return player.id !==action.payload
            })
        }
        case UPDATE_PLAYER:return{
            ...state,
            leaguePlayers: state.leaguePlayers.map(player=>{
                if(player.id === action.payload.id){
                    return action.payload
                }
            return player}),
            error:''
        }
        case POST_PLAYER: return{
            ...state,
            leaguePlayer: [...state.leaguePlayers, action.payload]
        }
        default: return state
    }
}
Enter fullscreen mode Exit fullscreen mode

Using the spread operator lets us copy the original state and manipulate the data. So, for the post-player method, we have the key leaguePlayer and defined its new values as an array with all the players' data along with the new player and appended at the end.
Those are the three key points of Redux; now we have to implement it into the project. We'll start off by creating a file called 'Store' and import the following from redux along with redux-thunk: createStore, combineReducers, applyMiddleware. The combineReducer allows the program to use multiple reducers by setting combineReducers to a variable, usually called rootReducer, and setting each reducer to its own key and value pair.

const rootReducer=combineReducers({
    players: playerReducer,
    teams: teamReducer,
    coaches:coachReducer,
    matches: matchReducer
})
Enter fullscreen mode Exit fullscreen mode

By setting createStore to a variable, we are able to pass in the rootReducer and applyMiddleware where we will pass in 'thunk' to applyMiddleware. The statement will look like this, where 'store' is how we will access the state in the program.

const store =createStore(rootReducer, applyMiddleware(thunk))
export default store
Enter fullscreen mode Exit fullscreen mode

Inside the program, we will want to import 'Provider' from react-redux, where the Provider component will be wrapped around the entire program of the App file and pass store={store} as a prop so every component will be able to use the state.

function App() {

  return(
    <Provider store={store}>
    <div class='background'>
      <NavBar />
      <Routes>
        <Route path="/" element={<Home />}></Route>
        <Route path="/players" element={<PlayersContainer />}></Route>
        <Route path="/coaches" element={<CoachesContainer />}></Route>
        <Route path="/teams" element={<TeamsContainer />}></Route>
        <Route path='/matches' element={<MatchesContainer />}></Route>
        <Route path="/add" element={<Add />}></Route>
        <Route path='/players/:id' element={<UpdatePlayer />}></Route>
        <Route path='/playerscoaches/:id' element={<ShowPlayersCoaches />}/>
        <Route path='/coachesplayers/:id' element={<ShowCoachesPlayers />}/>
        <Route path='/teamcoaches/:id' element={<ShowTeamCoaches />}/> 
        <Route path='/teamplayers/:id' element={<ShowTeamPlayers />}/>
        <Route path='/coaches/:id' element={<UpdateCoach/>}/>
      </Routes> 
    </div>
    </Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Once we have a component that needs access to the state, we will need to import useSelector, how we select the state we want to use and useDispatch to manipulate the data from the actions we previously defined. Using the useSelector is fairly simple, as it only takes one line of code.

const players = useSelector(state=>state.players.leaguePlayers)
Enter fullscreen mode Exit fullscreen mode

The useDispatch is how we will update the old state and return the new state. By passing in the function of our actions to useDispatch we are able to manipulate the data correctly.

const dispatch=useDispatch()
dispatch(deletePlayer(passPlayer.id))
Enter fullscreen mode Exit fullscreen mode

To conclude, there are many aspects of Redux, but once you get the hang of it, it can make the life of a programmer ten times easier. You won't need to pass down data to each child component, but instead, Redux will manage and keep the state updated for the other components, so you don't have to.

Top comments (0)