title | slug |
---|---|
React Redux Implement React Redux |
react--implement-redux-react-redux |
The following steps implement React Redux in a react project.
Import redux into your project.
npm i --save redux;
This adds Redux as a dependency to the project.
There are a few more things we to set up before we can implement Redux in React.
Add react-redux as a dependancy.
npm i --save react-redux;
Imagine this as the glue that binds Redux with React.
Redux is very strict about how it allows state to be modified. Changes to state can only be implement through actions which you will define.
Create a folder named: 'src/actions'
Create a file in this folder: 'src/actions/index.js'
Imagine you want to store and manage passwords in your app. The actions need to create new passwords, delete existing passwords, and update existing passwords.
You will implement the store in a following step. The store will be defined as an array and each password will be stored at an index in that array.
Define these actions in 'src/actions/index.js'
export const ADD_PASSWORD = "ADD_PASSWORD"
export const EDIT_PASSWORD = "EDIT_PASSWORD"
export const DELETE_PASSWORD = "DELETE_PASSWORD"
These are the action types. You need to export these so these string constants can be shared throughout your code.
Next add some action creators.
export const addPassword = (name, password) => {
return {
type: ADD_PASSWORD,
payload: { name, password }
}
}
export const deletePassword = (index) => {
return {
type: DELETE_PASSWORD,
payload: { index }
}
}
export const editPassword = (index, name, password) => {
return {
type: EDIT_PASSWORD,
payload: { index, name, password }
}
}
These functions are the action creators. These are simple functions that return action objects.
Every action object has a type, which is set to an action type, and a payload. Payload is a JS object with any properties.
Create a new folder: 'src/reducers'
Then add a new file to this folder: 'src/reducers/index.js'
Add another file: 'src/reducers/password-reducer.js'
In 'password-reducer.js' define a reducer function.
import { ADD_PASSWORD, DELETE_PASSWORD, EDIT_PASSWORD } from '../actions'
const passwordReducer = (state = [], action) => {
switch(action.type) {
case ADD_PASSWORD:
const { name, password } = action.payload
return [...state, { name, password }]
case DELETE_PASSWORD:
const { index } = action.payload
return [...state.slice(0, index), ...state.slice(index + 1)]
case EDIT_PASSWORD:
return state.map((item, index) => {
if (index !== action.payload.index) {
return item
}
return { ...item, ...action.payload }
})
default:
return state
}
}
export default passwordReducer
This block of code imports the Action Types.
It also defines the passwordReducer
function.
This function is responsible for providing the default value for state. The default state is defined here as the default value for the state parameter.
const passwordReducer = (state = [], action) => {...
The switch statement in the function handles each action type. Each case returns state. State is an array and when state is modified rather modifying state each case returns a new copy of the array.
This is a requirement for Redux! Any changes to state must produce new state! You can not modify existing state.
The store is a JavaScript object with properties that represent pieces of application state. Each reducer is responsible for managing one piece of state.
Add the following to 'src/reducers/index.js'
import { combineReducers } from 'redux'
import passwordReducer from './password-reducer'
export default combineReducers({
passwords: passwordReducer
})
This imports the combineReducers
method from 'react-redux' and the
passwordReducer
from 'src/reducers/password-reducer.js'
In this case the store will hold the array of passwords under the
key: 'passwords' and handle changes to this piece of state
with passwordReducer
.
Provider is a React Component that provides the Redux store to it's child components. Provider is part of react-redux.
Add this at the top of App.js.
import { createStore } from 'redux'
import { Provider } from 'react-redux'
Next import your reducers:
import reducers from './reducers'
Now create a store from your reducers:
const store = createStore(reducers)
Define the Provider for the App. This is a component that should be an ancestor to components that want access to the Store.
function App() {
return (
<Provider store={store}>
<div className="App">
<Password />
</div>
</Provider>
);
}
At this stage you are implementing Redux and have defined a store. The next step will be to connect components to the store.
This a component that will list all of the passwords in the store.
Create a new component that will display a list of passwords. Create a new file: 'src/password-list.js'.
import React, { useState } from 'react'
import { connect, useSelector } from 'react-redux'
function PasswordList() {
const passwords = useSelector((state) => state.passwords)
const passwordList = passwords.map((pass, index) => {
return (
<div key={index}>
name:{pass.name} password: {pass.password}
</div>)
})
return (
<div>
{passwordList}
</div>
)
}
export default PasswordList
in your App component, make sure to import the Password List component so we we can see the list of passwords
import PasswordList from './password-list';
...
<PasswordList />
Here you imported useSelector
from react-redux. You used this to get the list of passwords from the store with:
const passwords = useSelector((state) => state.passwords)
The function passed to useSelector()
takes state as a parameter and returns a value that you want from state. Here you returned passwords
from state.
Currently the Password component generates a password we'd like to be able to add a password to a list of saved passwords.
Besides adding a password we'd also like to include a name with every password we save.
Open the Password Component. Edit the constructor to add a new value on state that will hold the name.
Use a hook to keep track the value in the field:
import React, { useState } from 'react'
Add a new value and setter for the name:
const [name, setName] = useState('')
Add a new input field to show and edit this value. This should go above the password input in the render method.
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
Use the useDispatch hook. Import it at the top along with the action creator function addPassword.
import { useDispatch } from 'react-redux'
import { addPassword } from './actions'
Add a button that does this within the render method:
<div>
<button onClick={(e) => {
const dispatch = useDispatch()
dispatch(addPassword(name, password))
}}>Save</button>
</div>
Clicking the 'Save' button should add a new password to the list. Doing this should display the name and password to the PasswordList.