react用Redux中央倉庫實(shí)現(xiàn)一個(gè)todolist
本文實(shí)例為大家分享了react用Redux中央倉庫實(shí)現(xiàn)一個(gè)todolist的具體代碼,供大家參考,具體內(nèi)容如下

Redux簡單介紹
Redux是一個(gè)用來管理管理數(shù)據(jù)狀態(tài)和UI狀態(tài)的JavaScript應(yīng)用工具。隨著JavaScript單頁應(yīng)用(SPA)開發(fā)日趨復(fù)雜,JavaScript需要管理比任何時(shí)候都要多的state(狀態(tài)),Redux就是降低管理難度的。(Redux支持React,Angular、jQuery甚至純JavaScript)
Redux Dev Tools插件 Redux調(diào)試工具 谷歌商店下載
redux三個(gè)坑:
store倉庫必須是唯一的,多個(gè)store是堅(jiān)決不允許,只能有一個(gè)store空間
只有store能改變自己的內(nèi)容,Reducer不能改變
Reducer必須是純函數(shù)
Redux-thunk這個(gè)Redux最常用的插件:
在Dispatch一個(gè)Action之后,到達(dá)reducer之前,進(jìn)行一些額外的操作,就需要用到middleware(中間件)
在實(shí)際工作中你可以使用中間件來進(jìn)行日志記錄、創(chuàng)建崩潰報(bào)告,調(diào)用異步接口或者路由
npm install --save redux-thunk
第一步 倉庫 在store文件夾下新建index.js
//applyMiddleware,compose是為了使用下面兩個(gè)插件
import {createStore,applyMiddleware,compose} from 'redux' //引入redux
import thunk from 'redux-thunk' //引入redux中間件插件
import reducer from './reducer' //引用reducer中的數(shù)據(jù)
//瀏覽器安裝的倉庫插件 調(diào)試面板
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
//redux中間件插件 此函數(shù)為了兼容兩個(gè)插件并行
const enhancer = composeEnhancers(applyMiddleware(thunk))
//定義一個(gè)倉庫 唯一的 不能有兩個(gè)倉庫 createStore倉庫只接收兩個(gè)參數(shù)
const store = createStore( reducer, enhancer) // 創(chuàng)建數(shù)據(jù)存儲(chǔ)倉庫
export default store //將倉庫導(dǎo)出
新建reducer.js 做倉庫數(shù)據(jù)處理
import {ADD_ITEM , DELETE_ITEM , GET_LIST} from './actionTypes' //定義type類型的js文件
const defaultState = {
value:'sss',
list:[] //后端獲取的列表數(shù)據(jù)放在這里
}
// state: 指的是原始倉庫里的狀態(tài)。
// action: 指的是action新傳遞的狀態(tài)。
export default (state = defaultState,action)=>{
// console.log(state)
//Reducer里只能接收state 不能改變state
// if(action.type ==="changeInput"){
// let newState = JSON.parse(JSON.stringify(state)) //深拷貝state的值 轉(zhuǎn)成字符串 賦值給一個(gè)變量
// newState.value = action.vlaue //改變placeholder的值等于用戶輸入的值
// return newState //將新state return出去
// }
//增加
if(action.type === ADD_ITEM ){ //根據(jù)type值,編寫業(yè)務(wù)邏輯
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(action.value) //用戶輸入的新內(nèi)容push新的內(nèi)容到列表中去
console.log(action)
newState.value = '' //增加后清空
return newState
}
//刪除
if(action.type === DELETE_ITEM ){
let newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index,1) //刪除數(shù)組中對(duì)應(yīng)的值
return newState
}
//后端獲取數(shù)據(jù) 傳遞給中央倉庫做處理
if(action.type === GET_LIST ){
let newState = JSON.parse(JSON.stringify(state))
newState.list =action.data
return newState
}
return state
}
actionTypes.js 集中管理頁面reducer的type類型
//集中管理頁面reducer的type類型 export const ADD_ITEM = "addItem" //定義常量一般用大寫 export const DELETE_ITEM = "deleteItem" export const GET_LIST = "getListAction"
actionCreators.js 封裝組件的action
//封裝組件的action
import {ADD_ITEM , DELETE_ITEM ,GET_LIST} from './actionTypes' //定義type類型的js
import axios from 'axios'
//組件addItem里的action type已經(jīng)封好 所以把value作為參數(shù)用箭頭函數(shù)(value)=>傳進(jìn)來即可
//增加數(shù)據(jù)
export const addItem = (value)=>({
type:ADD_ITEM,
value
})
//刪除數(shù)據(jù)
export const deleteItem = (index)=>({
type:DELETE_ITEM,
index
})
//獲取數(shù)據(jù)
export const getListAction = (data)=>({
type:GET_LIST,
data
})
export const getTodoList = () =>{
return (dispatch)=>{
axios.get('https://www.easy-mock.com/mock/5d63d7ca5774121e1a634378/demo1/demo1')
.then((res)=>
{
const data = res.data.data;
const action = getListAction(data)
dispatch(action) //將action這個(gè)值傳給倉庫
})
.catch((error)=>{
console.log(error)
})
}
}
TodoList.js 組件js部分
import React, { Component } from 'react';
import TodoListUi from './TodoListUi' //組件UI部分
import store from '../store/index' //組件中獲得store中的數(shù)據(jù)
//import {ADD_ITEM , DELETE_ITEM} from '../store/actionTypes' //定義type類型的js 為了更方便檢查錯(cuò)誤 寫錯(cuò)會(huì)報(bào)錯(cuò)
import { addItem,deleteItem,getTodoList } from '../store/actionCreators' //封裝的action
//用reducer寫todolist 調(diào)用中央倉庫
class TodoList extends Component {
constructor(props){
super(props)
// console.log(store.getState()) //getState方法取出倉庫的值
this.state = store.getState() //將組件state數(shù)據(jù)賦值給倉庫數(shù)據(jù)
this.changeInputVlaue = this.changeInputVlaue.bind(this) //給方法做this綁定
this.storeChange = this.storeChange.bind(this)
this.clickBtn = this.clickBtn.bind(this)
this.deleteItem = this.deleteItem.bind(this)
store.subscribe(this.storeChange) //訂閱模式 改變數(shù)據(jù)時(shí)同步讓倉庫中的數(shù)據(jù)改變
}
render() {
return (
<TodoListUi
value={this.state.value}
changeInputVlaue={this.changeInputVlaue}
clickBtn={this.clickBtn}
list={this.state.list}
deleteItem = {this.deleteItem}
></TodoListUi>
);
}
componentDidMount(){
// axios.get('https://www.easy-mock.com/mock/5d63d7ca5774121e1a634378/demo1/demo1')
// .then((res)=>
// {
// const data = res.data.data;
// const action =getListAction(data) //將取到的數(shù)據(jù)封入action
// store.dispatch(action) //傳遞給reducer
// })
// .catch((error)=>{
// console.log(error)
// })
const action = getTodoList() //使用中間件獲取數(shù)據(jù)
store.dispatch(action) //傳給倉庫
}
//用戶輸入的值傳給倉庫 要通過dispatch()方法傳遞給store
//Action就是一個(gè)對(duì)象,這個(gè)對(duì)象一般有兩個(gè)屬性,第一個(gè)是對(duì)Action的描述,第二個(gè)是要改變的值。
//之前注銷的方法,在reducer里深拷貝完state里面的數(shù)據(jù),無法同步將用戶輸入賦值給state
changeInputVlaue(e){
this.setState({
value:e.target.value //將用戶輸入的value綁定給倉庫中的value,監(jiān)聽用戶輸入
})
// const action = {
// type:'changeInput', // 名字
// value:e.target.value //值
// }
// store.dispatch(action)
}
//state和組件的值同步互相改變
storeChange(){
this.setState(store.getState())
}
//增加 因?yàn)閘ist數(shù)據(jù)存在中央倉庫里 所以要做的是 將組件數(shù)據(jù)傳給倉庫 改變倉庫數(shù)據(jù)后 再返回給組件展示
clickBtn(){
// console.log(this.state.value)
// const action = {
// type:ADD_ITEM,
// value:this.state.value //獲取到用戶value,用于push
// }
const action = addItem(this.state.value);
store.dispatch(action)
}
//刪除
deleteItem(index){
// console.log(index)
// const action = {
// type:DELETE_ITEM,
// index //index傳過去用于刪除
// }
const action =deleteItem(index)
store.dispatch(action)
}
}
export default TodoList;
TodoListUi.js 組件UI部分抽離成子組件
//此文件用于視圖和邏輯的分離
import React from 'react';
import 'antd/dist/antd.css' //引入Ant Design UI庫
import { Input ,Button,List} from 'antd' //引入input組件
//無狀態(tài)組件 提高性能 將組件改造成函數(shù)
const TodoListUi = (props)=>{
return (
<div style={{margin:"100px"}}>
<div>
<Input
style={{ width:"250px",marginRight:"20px"}}
onChange={props.changeInputVlaue}
value={props.value}
/>
<Button type='primary' onClick={props.clickBtn}>增加</Button>
</div>
<div style={{margin:"10px",width:"300px"}}>
<List
bordered //加邊框
dataSource={props.list} //渲染什么數(shù)據(jù)
renderItem={(item,index)=>(<List.Item onClick={()=>{props.deleteItem(index)}}>{item}</List.Item>)} //每項(xiàng)
/>
</div>
</div>
);
}
//改造前組件 上邊需要從react引入Component
// class TodoListUi extends Component {
// state = { }
// render() {
// return (
// <div style={{margin:"100px"}}>
// <div>
// <Input
// style={{ width:"250px",marginRight:"20px"}}
// onChange={this.props.changeInputVlaue}
// value={this.props.value}
// />
// <Button type='primary' onClick={this.props.clickBtn}>增加</Button>
// </div>
// <div style={{margin:"10px",width:"300px"}}>
// <List
// bordered //加邊框
// dataSource={this.props.list} //渲染什么數(shù)據(jù)
// renderItem={(item,index)=>(<List.Item onClick={()=>{this.props.deleteItem(index)}}>{item}</List.Item>)} //每項(xiàng)
// />
// </div>
// </div>
// );
// }
// }
export default TodoListUi;
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
React styled-components設(shè)置組件屬性的方法
這篇文章主要介紹了styled-components設(shè)置組件屬性的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-08-08
原生實(shí)現(xiàn)一個(gè)react-redux的代碼示例
這篇文章主要介紹了原生實(shí)現(xiàn)一個(gè)react-redux的代碼示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06
React+Typescript項(xiàng)目環(huán)境搭建并使用redux環(huán)境的詳細(xì)過程
這篇文章主要介紹了React+Typescript項(xiàng)目環(huán)境搭建并使用redux環(huán)境的詳細(xì)過程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
react反向代理使用http-proxy-middleware問題
這篇文章主要介紹了react反向代理使用http-proxy-middleware問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
react如何修改循環(huán)數(shù)組對(duì)象的數(shù)據(jù)
這篇文章主要介紹了react如何修改循環(huán)數(shù)組對(duì)象的數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

