You'll learn to:
- Install dependencies
- Structure Files
- Create Store
- Provide Store
- Add reducer slice
- Use redux in your view/component
npm install react-redux @reduxjs/toolkit
Redux
├──slices
│ ├──taskListSlice.js
│ └──...other slices
└──store.js
Contains the state of the app and the reducers divided in slices. Single source of truth principle.
//store.js
import { configureStore } from '@reduxjs/toolkit';
export const store = configureStore()
In your src/index.js, import react-redux and provide the store
//src/index.js
//... other imports
import { store } from './redux/store';
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
//...
In taskListSlice.js, pass the following arguments to createSlice:
- Give a name to your slice.
- Initialize your state.
- Write your reducers (think about the reducers that your app will use, i.e. add task, delete task, edit task, etc.). Remember immutability when writting your reducers. Each reducer always takes the previous state as first argument and the action optionally as the second.
//src/redux/slices/taskListSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
tasks: [],
};
const taskListSlice = createSlice({
name: 'tasklist',
initialState,
reducers: {
addTask: (state, action) => {
const newTask = {
date: new Date().toJSON(),
title: action.payload,
completed: false,
position: state.tasks.length + 1
};
return { ...state, tasks: [...state.tasks, newTask] }
},
//Other reducers
//...
}
});
//Export the actions to be dispatched fron the views
export const { addTask /*, other reducers* */} = taskListSlice.actions;
//Export the reducer to be imported in the Store
export default taskListSlice.reducer;
Named Export vs Default Export in ES6
In your store.js, add your slice, it shoud look like this
//src/redux/store.js
import { configureStore } from '@reduxjs/toolkit';
import taskListSlice from './slices/taskListSlice';
export const store = configureStore({
reducer:{
taskList:taskListSlice
//... Other slices
}
});
Your view/component will need to:
- Read your redux state (subscribe)
- Change your redux state (dispatch)
import { useSelector } from 'react-redux';
const ToDoList = () => {
const taskList = useSelector((state) => state.taskList.tasks);
return <section>
//print cards using taskList.map
</section>
In your components, import the dispatcher and the actions
import { useDispatch } from 'react-redux';
import { addTask } from '../../../redux/slices/taskListSlice';
In your function component
const ToDoList =()=>{
const dispatch = useDispatch();
//event handler
const addItem = (event) => {
event.preventDefault();
dispatch(addTask(newTaskInput.current.value));
};
return <section>
//...
<button onClick={addItem}>Add Item</button>
//...
</section>
};
In your event handler, dispatch your reducer with your action. To dispatch the action you only need to pass the payload as argument.