Simplest Redux
Tags: redux, react, javascript
Published: 2020-09-11 11:19:21

This article is for someone who wants to implement redux without going into depth

--------------
if you're in for only the code part skip to Implementation

### Redux brief
Redux is aimed to put the app's state at one accessible place for all components (single source of truth) called the store

This store have our state, the store takes the reducers to adjust in the state depending on the actions taken by an interaction from the user adding item to cart or liking a picture

Actions are objects who must have a type property

Action creators are functions that return objects or functions

reducers are clean functions who has no side effects

### Middleware brief(Thunk - logger)

middleware is made to intervene after an action is triggered and before it reaches the reducer aka making a change to the state

thunk middleware is used for async actions and it gets triggered when the action creator returns a function not an object (redux-thunk npm)

logger middleware is to log the action and the state 

```
const logger = (store) => (next) => (action) => {
  console.group(action.type)
  console.log('the action', action)
  const result = next(action)
  console.log('the new state' ,store.getState() )
  console.groupEnd()
  return result
}  
```
### Implementation

Three dependencies needed, the first is "react-redux", the second is "redux" and the third is "redux-thunk" 

##### index.js
a- you take your Provider from react-redux and this will open the door to something called connect which in the end when applied will allow the consumer components consume state when passed through connect as props

b- you create the store via createStore function from redux by passing to it as a first argument your reducer 

c- if multiple reducers you use combineReducers from redux

d- CreateStore can take as a second argument the middleware through the applyMiddleware function which its arguments are the used middleware
```
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import {createStore, combineReducers, applyMiddleware} from 'redux';
import thunk from 'redux-thunk'
import {firstReducer} from './reducers/firstReducer';
import {secondReducer} from './reducers/secondReducer';
import App from './components/App';

// the logger function is a middleware function 
const logger = (store) => (next) => (action) => {
  console.group(action.type)
  console.log('the action', action)
  const result = next(action)
  console.log('the new state' ,store.getState() )
  console.groupEnd()
  return result
}  

//creation of store
const store = createStore(
  combineReducers({firstReducer,secondReducer,moviesReducer}),
  applyMiddleware(thunk,logger)
)


ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
```
##### Reducer
any reducer would be the same idea 
state is given its initial value which in this case is an object
```
export const firstReducer = (state={},action) => {
  switch (action.type) {
    case 'ACTION_TYPE':
      return {...state,value:action.payload}
    default:
      return state;
  }
}
```
#####Actions
```
//action taking an argument to set a value in the state 
export const actionCreator = (value) => ({
  type:'ACTION_TYPE',
  payload:value
})


//another action that returns a function to be handled by
//thunk for async call to get for example movies
//you would create an action for loading and then another to
//set the movies
export const getMovies = () => {
  return (dispatch) => {
      dispatch(loadingMovies())
    return fetch('api')
    .then((res)=> res.json())
    .then((res)=>dispatch(setMovies(res)))
  }
}
```
##### Component A that creates the call
```
import React from 'react';
import {connect} from 'react-redux';
import {getMovies} from '../../actions/movies'

class ComponentA extends React.Component{

  componentDidMount() {
    this.props.movies()
  }

  render(){
    return(
      <div>
       <p> i'm Component A let get those movies </p>
      </div>
    )
  }
}

const mapDispatchToProps = (dispatch) => ({
  movies: ()=> dispatch(getMovies())
})

export default  connect(null,mapDispatchToProps)(ComponentA);

```
##### Component B that will display movies once returned

```
import React from 'react';
import {connect} from 'react-redux';

function ComponentB ({movies,loading}){
  return(
    <div>
      <div>
        <h3>movies</h3>
        <ul>
          {loading
            ? <div>loading ...</div>
            :movies.map((movie,id)=>(
            <div key={id}>
                 <li > {movie.title} </li>
            </div>
          ))}
        </ul>
      </div>
    </div>
  )
}

const mapStateToProps = (state) => ({
  movies: state.moviesReducer.movies,
  loading: state.moviesReducer.loading
})

List.defaultProps={
  movies:[],
  loading:Boolean
}

export default connect(mapStateToProps)(ComponentB)

```