Redux 进阶
阐述
接下来我们学习一下如何从后台取得数据,并和Redux结合,实现想要的业务逻辑。
比如以前我们的列表数据是在Reducer里写死的,本文就使用Axios从后台获取数据。
利用php创建模拟数据
格式
{
"data": {
"list": [
'早起跑步锻炼身体',
'中午下班休息一小时',
'晚上8点到10点,学习两个小时'
]
}
}
test.php
<?php
header('Access-Control-Allow-Origin: *');
$json = '{
"data": {
"list": [
"早起跑步锻炼身体",
"中午下班休息一小时",
"晚上8点到10点,学习两个小时"
]
}
}';
// $arr = json_decode($json,true);
echo $json;
安装并使用Axios
因为在Redux的学习中,我们使用了新的项目和目录,所以要重新安装Axios插件(以前安装的不能再使用了)。
直接使用npm进行安装。
npm install --save axios
安装完成后,就可以在 TodoList.js
中,引入并进行使用了。
import axios from 'axios'
引入后,在组件的声明周期函数里 componentDidMount
获取远程接口数据。
componentDidMount(){
axios.get('http://tt.cc/test.php').then((res)=>{
console.log(res)
})
}
做完这一步骤后,可以在浏览器中打开,预览下是否控制台(console)获取数据,如果可以获取,说明完全正常。
获取数据后跟Redux相结合(重点)
接下来就可以把得到的数据放到Redux的store中了,这部分和以前的知识都一样,我就尽量给出代码,少讲理论了。
先创建一个函数,打开以前写的 store/actionCreatores.js
函数,然后写一个新的函数,代码如下:
export const getListAction = (data)=>({
type:GET_LIST,
data
})
这时候保存会显示找不到 GET_LIST
,我们再到 actionTypes.js
文件中加入一个常量。
export const GET_LIST = 'getList'
然后引入到 actionCreatores.js
中。
import {CHANGE_INPUT , ADD_ITEM , DELETE_ITEM , GET_LIST} from './actionTypes'
这步完成后,回到 TodoList.js
文件,继续编写axios中的回调内容,在写之前,记得先把getListAction进行引入。
import {changeInputAction , addItemAction ,deleteItemAction,getListAction} from './store/actionCreatores'
componentDidMount(){
axios.get('http://tt.cc/test.php').then((res)=>{
const data = res.data
const action = getListAction(data)
store.dispatch(action)
})
}
现在数据已经通过 dispatch
传递给 store
了,接下来就需要 reducer 处理业务逻辑了。
打开 reducer.js
代码如下(详细步骤在代码中作了注释):
//----关键代码--------start --------引入GET_LIST
import {CHANGE_INPUT,ADD_ITEM,DELETE_ITEM,GET_LIST} from './actionTypes'
//----关键代码--------end
const defaultState = {
inputValue : 'Write Something',
//----关键代码--------start --------删除原来的初始化代码,减少冗余
list:[]
}
export default (state = defaultState,action)=>{
if(action.type === CHANGE_INPUT){
let newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue = action.value
return newState
}
if(action.type === ADD_ITEM ){
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue) //push新的内容到列表中去
newState.inputValue = ''
return newState
}
if(action.type === DELETE_ITEM ){ //根据type值,编写业务逻辑
let newState = JSON.parse(JSON.stringify(state))
newState.list.splice(action.index,1) //push新的内容到列表中去
return newState
}
//----关键代码--------start --------
if(action.type === GET_LIST ){ //根据type值,编写业务逻辑
let newState = JSON.parse(JSON.stringify(state))
newState.list = action.data.data.list //复制性的List数组进去
return newState
}
//----关键代码--------end --------
return state
}
这样就完成了一次从后台请求数据,然后和Redux结合的过程。
希望小伙伴都能练习一下,我们的程序员越来越像真实的开发了,小伙伴也要在练习中不断熟悉这种开发模式。
demo
demo01\src\index.js
import React from 'react';
import ReactDOM from 'react-dom'
import TodoList from './TodoList'
ReactDOM.render(<TodoList/>,document.getElementById('root'))
demo01\src\TodoList.js
import React, { Component } from 'react';
import store from './store'
//关键代码-------------start
import {changeInputAction , addItemAction ,deleteItemAction,getListAction} from './store/actionCreators'
//关键代码------------end
import TodoListUI from './TodoListUI'
import axios from 'axios'
class TodoList extends Component {
constructor(props){
super(props)
this.state=store.getState();
this.changeInputValue= this.changeInputValue.bind(this)
this.storeChange = this.storeChange.bind(this)
this.clickBtn = this.clickBtn.bind(this)
store.subscribe(this.storeChange) //订阅Redux的状态
}
render() {
return (
<TodoListUI
inputValue={this.state.inputValue}
list={this.state.list}
changeInputValue={this.changeInputValue}
clickBtn={this.clickBtn}
deleteItem={this.deleteItem}
/>
);
}
componentDidMount(){
axios.get('http://tt.cc/test.php').then((res)=>{
const data = res.data
const action = getListAction(data)
store.dispatch(action)
})
}
storeChange(){
// console.log('store changed')
this.setState(store.getState())
}
//--------关键代码------start
changeInputValue(e){
const action = changeInputAction(e.target.value)
store.dispatch(action)
}
clickBtn(){
const action = addItemAction()
store.dispatch(action)
}
deleteItem(index){
console.log(index)
const action = deleteItemAction(index)
store.dispatch(action)
}
//--------关键代码------end
}
export default TodoList;
demo01\src\TodoListUI.js
import React from 'react';
import 'antd/dist/antd.css'
import { Input , Button , List } from 'antd'
const TodoListUi = (props)=>{
return(
<div style={{margin:'10px'}}>
<div>
<Input
style={{ width:'250px', marginRight:'10px'}}
onChange={props.changeInputValue}
value={props.inputValue}
/>
<Button
type="primary"
onClick={props.clickBtn}
>增加</Button>
</div>
<div style={{margin:'10px',width:'300px'}}>
<List
bordered
dataSource={props.list}
renderItem={
(item,index)=>(
<List.Item onClick={()=>{props.deleteItem(index)}}>
{item}
</List.Item>
)
}
/>
</div>
</div>
)
}
export default TodoListUi;
demo01\src\store\index.js
import { createStore } from 'redux' // 引入createStore方法
import reducer from './reducer'
const store = createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) // 创建数据存储仓库
export default store //暴露出去
demo01\src\store\reducer.js
import {CHANGE_INPUT,ADD_ITEM,DELETE_ITEM,GET_LIST} from './actionTypes'
const defaultState = {
inputValue : 'Write Something',
list:[
'工作再忙也要锻炼身体',
'中午下班休息一小时'
]
}
const stateAction = (state = defaultState,action)=>{
if(action.type === CHANGE_INPUT){
let newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue = action.value
return newState
}
//state值只能传递,不能使用
if(action.type === ADD_ITEM ){
//根据type值,编写业务逻辑
let newState = JSON.parse(JSON.stringify(state))
//push新的内容到列表中去
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
}
//根据type值,编写业务逻辑
if(action.type === DELETE_ITEM ){
let newState = JSON.parse(JSON.stringify(state))
//push新的内容到列表中去
newState.list.splice(action.index,1)
return newState
}
if(action.type === GET_LIST ){ //根据type值,编写业务逻辑
let newState = JSON.parse(JSON.stringify(state))
newState.list = action.data.data.list //复制性的List数组进去
return newState
}
return state
}
export default stateAction;
demo01\src\store\actionTypes.js
export const CHANGE_INPUT = 'change_input_value'
export const ADD_ITEM = 'addItem'
export const DELETE_ITEM = 'deleteItem'
export const GET_LIST = 'getList'
demo01\src\store\actionCreators.js
import {CHANGE_INPUT , ADD_ITEM , DELETE_ITEM , GET_LIST} from './actionTypes'
export const changeInputAction = (value)=>({
type:CHANGE_INPUT,
value
})
export const addItemAction = ()=>({
type:ADD_ITEM
})
export const deleteItemAction = (index)=>({
type:DELETE_ITEM,
index
})
export const getListAction = (data)=>({
type:GET_LIST,
data
})