22.标准的redux工作模型
初始化项目目录
- src
- actions
- components
- reducers
- App.js
- index.js
- store.js
接口地址:http://jsonplaceholder.typicode.com/posts
1.在App.js
中引入BlogList
组件
import React,{Componet} from 'react';
import {BlogList} from './componets';
class App extends Componet{
render(){
return (
<div><BlogList/></div>
)
}
}
export default App;
2.新建文件src/components/index.js
export {default as BlogList} from './BlogList/BlogList'
3.新建文件src/components/BlogList/BlogList.js
import React, {Component} from 'react';
import BlogItem from './BlogItem';
class BlogList extends Component {
//这里还需要对传入的数据做检测 prop-types
render() {
return (
<ul>
<BlogItem/>
</ul>
);
}
}
export default BlogList;
4.新建文件src/components/BlogList/BlogItem.js
import React from 'react'
export default function BlogItem(){
return(
<li>BlogItem</li>
)
}
5.新建文件src/reducers/index.js
import { combineReducers } from 'redux'
import Blog from './blog'
export default combineReducers({
blog
})
6.新建文件src/reducers/blog.js
//初始化数据
const initState=[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}
];
export default (state=initState, action) => {
switch (action.type) {
default:
return state;
}
}
7.创建store.js
import {createStore,applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
export default createStore(
rootReducer,
applyMiddleware(thunk),//使用中间件
);
8.引用Provider src/index.js
import React from 'react'
import {render} from 'react-dom'
import App from './App'
//Provider是react-redux提供的组件
import {Provider} from 'react-redux'
import store from './store'
render(
<Provider store={store}>
<App/>
</Provider>,
document.getElementById("root")
);
9.使用store(connect) (src/components/BlogList/BlogList.js
)
import {connect} from 'rect-redux';
10.修改导出配置src/components/BlogList/BlogList.js
const mapState=state=>({
blogList:state.blog
})
export default connect(mapState)(BlogList)
11.添加加载状态src/reducers/blog.js
const initState = {
list: [
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}
],
isLoading:false,
};
12.修改结构时参数src/components/BlogList/BlogList.js
const mapState=state=>({
list:state.Blog.list,
isLoading:state.Blog.isLoading,
});
13.遍历数据src/components/BlogList/BlogList.js
render() {
console.log(this.props.list)
return (
<ul>
{
this.props.list.map(blog=>{
return (
<BlogItem key={blog.id} {...blog}/>
)
})
}
</ul>
);
}
14.修改子组件src/components/BlogList/BlogItem.js
import React from 'react'
export default function BlogItem(props){
return(
<li>
<h3>{props.title}</h3>
<p>{props.body}</p>
</li>
)
}
15.加上loading状态src/components/BlogList/BlogList.js
render() {
console.log(this.props.list)
const {
list,
isLoading
} = this.props;
return isLoading ? <div>loading...</div> :
<ul>
{
list.map(blog => {
return (
<BlogItem key={blog.id} {...blog}/>
)
})
}
</ul>
}
16.使用axios
进行数据请求
cnpm i -D axios
创建文件src/services/index.js
import axios from 'axios'
const ajax=axios.create({
baseURL:'http://jsonplaceholder.typicode.com',
})
export const getPosts=()=>ajax.get('/posts');
17.创建文件src/actions/actionTypes.js
export default{
START_FETCH_BLOG_LIST:'START_FETCH_BLOG_LIST',//正在请求
FETCH_BLOG_LIST_SUCCESS:'FETCH_BLOG_LIST_SUCCESS',//请求完成
FETCH_BLOG_LIST_FAILED:'FETCH_BLOG_LIST_FAILED',//请求失败
}
18.新建文件src/actions/blog.js
import actionTypes from './actionType'
import {getPosts} from "../services";
/**
* 开始请求
* @return {{type: string}}
*/
const startFetchBlogList=()=>{
return {
type:actionTypes.START_FETCH_BLOG_LIST
}
};
const fetchBlogListSuccess=(payload)=>{
return {
type:actionTypes.FETCH_BLOG_LIST_SUCCESS,
payload
}
};
const fetchBlogListFailed=()=>{
return {
type:actionTypes.FETCH_BLOG_LIST_FAILED
}
};
export const fetchBlogList=()=>dispatch=>{
dispatch(startFetchBlogList());
getPosts().then(res=>{
if(res.status===200){
dispatch(fetchBlogListSuccess({list:res.data}))
}else{
dispatch(fetchBlogListFailed())
}
}).catch(error=>{
console.log(error);
dispatch(fetchBlogListFailed())
})
};
19.引入action
(src/components/BlogList/BlogList.js
)
import {fetchBlogList} from "../../actions/blog";
componentDidMount() {
this.props.fetchBlogList()
}
20.src/reducers/blog.js
进行数据处理,及返回状态处理
import actionTypes from '../actions/actionType';
//初始化数据
const initState = {
list: [
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}
],
isLoading:false,
};
export default (state = initState, action) => {
switch (action.type) {
case actionTypes.START_FETCH_BLOG_LIST:
return{
...state,
isLoading:true,
};
case actionTypes.FETCH_BLOG_LIST_SUCCESS:
return {
...state,
isLoading:false,
list:action.payload.list
};
case actionTypes.FETCH_BLOG_LIST_FAILED:
return {
...state,
isLoading:false,
list:[{title:"没有数据啦"}]
};
default:
return state;
}
}
从深往浅理解:
1. `src/components/BlogList/BlogList.js`中调用了this.props.fetchBlogList();这个函数是从state中读取的并且使用connect()进行了传递,所以可以获取到this.props.fetchBlogList()这个函数
2. 函数定义位置是在`src/actions/blog.js`中导出的fetchBlogList函数
在fetchBlogList函数中进行了数据请求`getPost`函数,并且使用dispatch进行保存当前请求状态
在这里有一点知识难点,需要在请求成功后传值到下一个执行函数中`dispatch(fetchBlogListSuccess({.......}))`
3.使用dispatch函数调用的方法会被`src/reducers/index.js`文件进行接收,并以`combineReducers`进行合并,也就是最终调用位置为`src/reducers/blog.js`文件的默认导出函数,默认导出的函数处理当前状态及数据反回给`react-redux`(在`src/components/BlogList/BlogList.js`文件中有引用,)
4.最终的数据解析位置是在`src/components/BlogList/BlogList.js`的mapState中进行解析的数据