Redux 添加数据请求最后渲染

仓库代码:https://gitee.com/zhouyunfang/react-redux.git

目录结构:

Redux 添加数据请求最后渲染

1. postForm.js 为提交数据页面

触发action事件方法为 this.props.createPost(post)

import React, { Component } from 'react'

class PostFrom extends Component {
    constructor(props) {
        super(props)
        this.state = {
            title: '',
            body: ''
        };
        // this.onChange = this.onChange.bind(this)
    }
    onChange(e) {//把当前修改的值赋入state
        this.setState({
            [e.target.name]:e.target.value
        })
    }
    onSubmit(e) {
        // 阻止事件传递
       e.preventDefault();
        // 把表单用的最终数据从state中提取出来,传入请求
        const post ={
            title:this.state.title,
            body:this.state.body
        }
        // 触发redux 中的action方法,把需要提交的post参数传入
        this.props.createPost(post)//把以下原本在页面的fetch请求剪切至actions文件中的PostActions.js文件中
        // fetch('http://jsonplaceholder.typicode.com/posts',{
        //     // post提交
        //     method:"POST",
        //     headers:{
        //         "Content-type":"application/json"
        //     },
        //     body:JSON.stringify(post)//把提交的内容转字符串
        // })
        // .then(res =>res.json())
        // .then(data =>{
        //     console.log(data)
        // })
    }
    render() {
        return (
            <div>
                <h1>添加内容</h1>
                <form onSubmit={this.onSubmit.bind(this)}>
                    <div>
                        <label >title</label>
                        <br />
                        <input type="text" name="title" onChange={this.onChange.bind(this)} defaultValue={this.state.title} />
                    </div>
                    <div>
                        <label >body</label>
                        <br />
                        <textarea name="body" id="" cols="30" rows="10" onChange={this.onChange.bind(this)} defaultValue={this.state.body}></textarea>
                    </div>
                    <br />
                    <button type="submit">添加</button>
                </form>
            </div>
        )
    }
}
export default PostFrom;

2. postActions.js

(在actions文件下的postActions.js中写入请求,请求成功后由dispatch进行分发,会分发至reducers文件中的

PostReducer.js文件中.

// 引入types.js文件
import { NEW_POST } from './types'

export const createPost = postData => dispatch => {//接收postFrom.js页面传过来的post参数这里形参为postData
    fetch('http://jsonplaceholder.typicode.com/posts', {
        // post提交
        method: "POST",
        headers: {
            "Content-type": "application/json"
        },
        body: JSON.stringify(postData)//把提交的内容转字符串
    })
        .then(res => res.json())
        .then(data => {
            dispatch({
                /**
                 * type是指定一定要有的,在这里定义的属性值,我们会把它抽离到types.js中
                 * NEW_POST是dispatch到我们的store中去store会返回到reducer当中,reducer要知道他是哪一个,返回哪一个状态
                 * 如果dispatch成功会返回到postReducer.js中去,在postreducer.js中去判断type属性值
                 *  */
                type: NEW_POST,
                // 把请求的data返回回去
                payload: data
            })
        })
}

3. PostReducer.js

(在PostReducer.js文件中对action下的type类型进行判断,判断之后把最新的修改数据 赋值并return出去,会return到reducers文件夹下的index.js中 

// 引入 dispatch的type类型
import { NEW_POST } from '../actions/types'
// reducer的作用: 返回新的状态
// 定义一个变量,
const initialState = {
    //存储你想要获取的状态 
    item: []//1.访问到当前的文件中的时候定义一个初始状态
}
export default function (state = initialState, action) {//reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
    switch (action.type) {//2.在switch的时候会传过来对应的数据,在此修改状态,返回给到初始定义的属性中最终返回到组件中去
        // 对用户添加数据的type类型进行判断 
        case NEW_POST:
            return {
                ...state,
                // 把postActions.js中分发成功的值赋给item
                item: action.payload
            }
        default:
            return state;
    }

}

4..reducers文件夹下的index.js

(之后会返回到posts.js组件中去最终渲染)

// reducer合成,redux自身提供的一个方法
import { combineReducers } from 'redux'
import postReducer from './PostReducer'
export default combineReducers({
    // 这里写生成状态的方法,这个方法会最后合成一个大的reducer,会拆分多个小的
    posts:postReducer,//这里是引的posts.js中的state数据

})

5. PostForm.js

在PostForm.js中引入PropType 规定方法和状态的使用类型,connect来连接createPost中的数据.

import React, { Component } from 'react'
// 给不前的状态规定一个数据类型,这是react给我们的一个标准
import propTypes from 'prop-types'
//1. 想让Posts使用fetchPost的方法 ,就要使用reducer中提供的connect来连接
import { connect } from 'react-redux'
// { createPost } 为es6 的解构方法 createPost是从postActions中解构出来的方法
import { createPost } from '../actions/postActions'

class PostForm extends Component {
    constructor(props) {
        super(props)
        this.state = {
            title: '',
            body: ''
        };
    }
    onChange(e) {//把当前修改的值赋入state
        this.setState({
            [e.target.name]:e.target.value
        })
    }
    onSubmit(e) {
        // 阻止事件传递
       e.preventDefault();
        // 把表单用的最终数据从state中提取出来,传入请求
        const post ={
            title:this.state.title,
            body:this.state.body
        }
        // 触发redux 中的action方法,把需要提交的post参数传入
        this.props.createPost(post)//把以下原本在页面的fetch请求剪切至actions文件中的PostActions.js文件中
    }
    render() {
        return (
            <div>
                <h1>添加内容</h1>
                <form onSubmit={this.onSubmit.bind(this)}>
                    <div>
                        <label >title</label>
                        <br />
                        <input type="text" name="title" onChange={this.onChange.bind(this)} defaultValue={this.state.title} />
                    </div>
                    <div>
                        <label >body</label>
                        <br />
                        <textarea name="body" id="" cols="30" rows="10" onChange={this.onChange.bind(this)} defaultValue={this.state.body}></textarea>
                    </div>
                    <br />
                    <button type="submit">添加</button>
                </form>
            </div>
        )
    }
}
// 规定方法和状态的使用类型
PostForm.propTypes ={
    // 第一个为当前的方法
    createPost:propTypes.func.isRequired,
    // 第二个为数组,是在PostReducer.js中定义的
    PostForm : propTypes.array.isRequired
}
// 用connect将PostFromt和createPost连接起来从而达到数据对接
export default connect(null,{createPost})(PostForm);

 

6.posts.js

    在postForm.js传递数据给到posts.js页面

   posts.js页面 调用componentWillReceiveProps()钩子函数中去更新渲染

   componentWillReceiveProps()钩子函数为组件发生改变触发

  在调用钩子函数时判断nextProps下有newPost,就unshift到this.props.posts并渲染出来,

import React, { Component } from 'react'
// 给不前的状态规定一个数据类型,这是react给我们的一个标准
import propTypes from 'prop-types'
//1. 想让Posts使用fetchPost的方法 ,就要使用reducer中提供的connect来连接
import { connect } from 'react-redux'
// fetchPost为在postActions定义的方法
import { fetchPost } from '../actions/postActions'

class Posts extends Component {
    componentDidMount() {
        /**
         * 3.调用fetchPost中的方法,把原本 需要在这里的请求的方法剪切到postAction.js中去
         * 触发action操作
         */
        this.props.fetchPost()
    }
    // 在组件发生改变的时候触发,用户添加数据后接收从PostForm.js页面传来的值进行渲染
    componentWillReceiveProps(nextProps){
        // 在调用钩子函数时判断nextProps下有newPost,就unshift到this.props.posts并渲染出来,
        if(nextProps.newPost){
            this.props.posts.unshift(nextProps.newPost)
        }
    }
    render() {//展示之前对state数组posts中的数据遍历
        // const postsItem = this.state.posts.map(post =>(
            // 使用reduce中的数据就这里就不能用this.state,而是改用props
        const postsItem = this.props.posts.map(post => (
            <div key={post.id}>
                <h3>{post.title}</h3>
                <p>{post.body}</p>
            </div>
        ))
        return (
            <div>
                {postsItem}
            </div>
        )
    }
}

// 规定方法和状态的使用类型
Posts.propTypes ={
    // 第一个为当前的方法
    fetchPost:propTypes.func.isRequired,
    // 第二个为数组,是在PostReducer.js中定义的
    posts : propTypes.array.isRequired
}
/**
 * 将返回回来的状态转化成我们的属性props
 */
const mapStateToProps = state => ({
    /**
     * state中的posts是在reducers中的index.js定义的posts
     * items 中posts的属性值是在postReducer.js中定义的初始值
     *  */
    posts: state.posts.items,
    newPost:state.posts.item
})
/**
 * 2.connect连接 
 * connect接收两个方法
 * connect(mapStateToProps, {fetchPost})
 * 
 *  */
export default connect(mapStateToProps, { fetchPost })(Posts);