This article mainly introduces in detail how to use Redux elegantly in React projects. Now I share it with you and give it as a reference.
Preface
Maybe your current project has not yet reached the level of applying Redux, but there is no harm in understanding it in advance. This article will not help everyone use Redux
Concept
First of all, what frameworks and tools will we use?
React
UI framework
Redux
State management tool, has nothing to do with React, Other UI frameworks can also use Redux
react-redux
React plug-in, which is used to facilitate the use of Redux
react in React projects -thunk
Middleware, role: support asynchronous action
Directory structure
Tips: Directories unrelated to Redux have been omitted
|--src |-- store Redux目录 |-- actions.js |-- index.js |-- reducers.js |-- state.js |-- components 组件目录 |-- Test.jsx |-- App.js 项目入口
Preparation
Step 1: Provide default values. Since Redux is used to manage data, the data must have default values, so we set the default value of state Place it uniformly in the state.js file
// state.js // 声明默认值 // 这里我们列举两个示例 // 同步数据:pageTitle // 异步数据:infoList(将来用异步接口获取) export default { pageTitle: '首页', infoList: [] }
Step 2: Create a reducer, which is the data that will actually be used in the future. We will uniformly place it in the reducers.js file
// reducers.js // 工具函数,用于组织多个reducer,并返回reducer集合 import { combineReducers } from 'redux' // 默认值 import defaultState from './state.js' // 一个reducer就是一个函数 function pageTitle (state = defaultState.pageTitle, action) { // 不同的action有不同的处理逻辑 switch (action.type) { case 'SET_PAGE_TITLE': return action.data default: return state } } function infoList (state = defaultState.infoList, action) { switch (action.type) { case 'SET_INFO_LIST': return action.data default: return state } } // 导出所有reducer export default combineReducers({ pageTitle, infoList })
Step 3 Step: Create action. Now we have created reducers, but there is no corresponding action to operate them, so let’s write action
// actions.js // action也是函数 export function setPageTitle (data) { return (dispatch, getState) => { dispatch({ type: 'SET_PAGE_TITLE', data: data }) } } export function setInfoList (data) { return (dispatch, getState) => { // 使用fetch实现异步请求 window.fetch('/api/getInfoList', { method: 'GET', headers: { 'Content-Type': 'application/json' } }).then(res => { return res.json() }).then(data => { let { code, data } = data if (code === 0) { dispatch({ type: 'SET_INFO_LIST', data: data }) } }) } }
Final step: Create store instance
// index.js // applyMiddleware: redux通过该函数来使用中间件 // createStore: 用于创建store实例 import { applyMiddleware, createStore } from 'redux' // 中间件,作用:如果不使用该中间件,当我们dispatch一个action时,需要给dispatch函数传入action对象;但如果我们使用了这个中间件,那么就可以传入一个函数,这个函数接收两个参数:dispatch和getState。这个dispatch可以在将来的异步请求完成后使用,对于异步action很有用 import thunk from 'redux-thunk' // 引入reducer import reducers from './reducers.js' // 创建store实例 let store = createStore( reducers, applyMiddleware(thunk) ) export default store
So far , we have completed all the preparation work for using Redux, and then we will use Redux in the React component
Start using
First, let’s write the entry file of the application APP.js
import React from 'react' import ReactDOM from 'react-dom' // 引入组件 import TestComponent from './components/Test.jsx' // Provider是react-redux两个核心工具之一,作用:将store传递到每个项目中的组件中 // 第二个工具是connect,稍后会作介绍 import { Provider } from 'react-redux' // 引入创建好的store实例 import store from '@/store/index.js' // 渲染DOM ReactDOM.render ( ( <p> {/* 将store作为prop传入,即可使应用中的所有组件使用store */} <Provider store = {store}> <TestComponent /> </Provider> </p> ), document.getElementById('root') )
The last is our component: Test.jsx
// Test.jsx import React, { Component } from 'react' // connect方法的作用:将额外的props传递给组件,并返回新的组件,组件在该过程中不会受到影响 import { connect } from 'react-redux' // 引入action import { setPageTitle, setInfoList } from '../store/actions.js' class Test extends Component { constructor(props) { super(props) } componentDidMount () { let { setPageTitle, setInfoList } = this.props // 触发setPageTitle action setPageTitle('新的标题') // 触发setInfoList action setInfoList() } render () { // 从props中解构store let { pageTitle, infoList } = this.props // 使用store return ( <p> <h1>{pageTitle}</h1> { infoList.length > 0 ? ( <ul> { infoList.map((item, index) => { <li>{item.data}</li> }) } </ul> ):null } </p> ) } } // mapStateToProps:将state映射到组件的props中 const mapStateToProps = (state) => { return { pageTitle: state.pageTitle, infoList: state.infoList } } // mapDispatchToProps:将dispatch映射到组件的props中 const mapDispatchToProps = (dispatch, ownProps) => { return { setPageTitle (data) { // 如果不懂这里的逻辑可查看前面对redux-thunk的介绍 dispatch(setPageTitle(data)) // 执行setPageTitle会返回一个函数 // 这正是redux-thunk的所用之处:异步action // 上行代码相当于 /*dispatch((dispatch, getState) => { dispatch({ type: 'SET_PAGE_TITLE', data: data }) )*/ }, setInfoList (data) { dispatch(setInfoList(data)) } } } export default connect(mapStateToProps, mapDispatchToProps)(Test)
Three principles of Redux
1. Single data source
The state of the entire application is stored in an object tree, and this object tree only exists in one store
2. State is read-only
The only thing that changes the state The method is to trigger action, which is an ordinary object used to describe the event that has occurred
3. Use pure functions to perform modifications
In order to describe how action changes the state tree, you need to write reducers
The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.
Related articles:
Detailed analysis of Vue Socket.io source code
Using native JavaScript to achieve the magnifying glass effect
Encapsulated cache class implemented through redis as cache in nodejs
The above is the detailed content of How to use Redux in React projects (detailed tutorial). For more information, please follow other related articles on the PHP Chinese website!