首先初始化创建一个项目,具体怎么创建不用说了吧
项目创建完后安装依赖:
npm install redux --save
npm install react-redux --save
npm install redux-thunk --save
npm install redux --save
npm install react-redux --save
npm install redux-thunk --save
在 src 目录下新建个 store 文件夹
store 文件夹下创建文件:actionTypes.js、reducer.js、actionCreators.js
目录结构长这样:
actionTypes.js
通过action更改state的内容,每个数据更改动作描述为一个action
一个action是一个简单的对象,用来描述state发生了什么变更。说白了就是一个对象
通过action更改state的内容,每个数据更改动作描述为一个action
一个action是一个简单的对象,用来描述state发生了什么变更。说白了就是一个对象
export const ADD_ARTICLE = "ADD_ARTICLE"
reducer.js
reducer是个函数,它接收state、action为参数,返回新的state。
reducer只能处理同步的代码,后续会说怎样处理异步问题
一般在store文件夹内创建一个reducer.js文件
import * as actionTypes from "./actionTypes" const initialState = { articles: [ { id: 1, title: "标题1", body: "内容1" }, { id: 2, title: "标题2", body: "内容2" }, ], } const reducer = (state = initialState, action) => { switch (action.type) { case actionTypes.ADD_ARTICLE: const newArticle = { id: Math.random(), // 随机id title: action.article.title, body: action.article.body, } return { ...state, articles: state.articles.concat(newArticle), } default:; } return state } export default reducer
处理异步代码
import * as actionTypes from "./actionTypes" export const addArticle = article => { return { type: actionTypes.ADD_ARTICLE, article, } } export const simulateHttpRequest = article => { return dispatch => { setTimeout(() => { // 模拟异步 dispatch(addArticle(article)) }, 3000) } }
然后改造一下src下的index文件让redux与项目连接起来
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import reportWebVitals from './reportWebVitals'; // redux套件 import { createStore, applyMiddleware } from "redux" import { Provider } from "react-redux" import thunk from "redux-thunk" import reducer from "./store/reducer" // 辅助函数Provider可以把store关联到React const store = createStore(reducer, applyMiddleware(thunk)) ReactDOM.render( // 用Provider组件包裹着App组件,store作为props值传入Provider。 <Provider store={store}> <App /> </Provider>, document.getElementById("root") ) reportWebVitals();
好了以上就是redux准备工作接下来就是到实际组件运用了
在 src 目录下新建个 components 文件夹
然后创建两个组件 A组件、B组件,目录结构长这样:a.jsx(A组件)
import React, { useState } from 'react'; function A({ saveArticle }) { const [article, setArticle] = useState() const handleArticleData = e => { setArticle({ // 添加数据 ...article, [e.target.id]: e.target.value, // id用于添加那个字段 }) } const add = ()=> { // 保存数据 saveArticle(article) } return ( <div className="A"> 我是A组件 <input type="text" id="title" placeholder="Title" onChange={handleArticleData} /> <input type="text" id="body" placeholder="Body" onChange={handleArticleData} /> <button onClick={add}>添加article</button> </div> ); } export default A;
b.jsx(B组件)
import React from 'react'; function B({articles}) { const renderArticles = ()=> { // 渲染列表 return articles.map(article => ( <div key={article.id}> <span>标题:{article.title}</span>, <span>内容:{article.body}</span> </div> )) } return ( <div className="B"> 我是B组件 {renderArticles()} </div> ); } export default B;
App页面做例子(src的App.js)里面引用A组件、B组件
import A from './components/a' import B from './components/b' import { connect } from "react-redux" import { simulateHttpRequest } from "./store/actionCreators" function App({ articles, saveArticle }) { return ( <div className="App"> <A articles={articles} saveArticle={saveArticle}/> <B articles={articles}/> </div> ); } /* mapStateToProps函数名可以随便改, 它从store中获取state值作为它的参数,返回了一个对象。 为了获取到store中的state,我们需要把 mapStateToProps() 作为connect函数的参数。 */ const mapStateToProps = state => { return { articles: state.articles, } } /* 在这里我们从actionTypes.js中引入了 everything 。 然后创建了一个新的函数mapDispatchToProps , 它接收dispatch作为参数。 */ const mapDispatchToProps = dispatch => { return { saveArticle: article => dispatch(simulateHttpRequest(article)), } } // connect:组件App获得redux的store export default connect( mapStateToProps, mapDispatchToProps )(App)
最终页面长这样:
通过redux,A组件做了更新,B组件自动更新
来个总结:
个人感觉小项目直接用hook完事,redux看情况用,
本文尽量用最简洁的代码实现redux的效果,没整其他的玩意干扰本文核心内容
还有很多redux技术点其实没提到,感觉自己学会、通过文字表达让别人理解是两回事
参考文章:https://zhuanlan.zhihu.com/p/103420294