react+redux实战——redux到底是个啥子?

react

写在前面

文章是个人初学redux的分享,从redux基础知识点到使用redux搭建简单的表单提交项目。

项目代码地址:https://github.com/jishuaizhen/react-redux-simple-project.git

项目学习视频:https://ke.qq.com/course/368915

一、redux到底是个啥子?

1.redux和vuex具有类似的作用,为了方便组件间的数据通信而产生。

2.简单理解:redux和vuex都提供了一个数据仓库,组件无法直接修改仓库中的数据,需要使用redux中提供的方法传参修改或者获取数据。

3.注意:redux涉及到三个比较重要的点:store、action、reducer;另外,在使用redux的时候参数也是传来传去的,比较麻烦,容易绕晕。

4.redux的详细介绍:阮一峰老师的博客http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html

5.

在图中可以看到,使用redux之后:1.用户触发组件中的事件,需要提交或者获取数据;2.action接到用户的操作并派发;3.action在派发过程会经过store,携带store中的数据和action(具体操作)提供给reducer;4.reducer处理之后返回最新的状态(也就是数据),更新store中的数据;5.当store发生变化之后,组件获取数据进行页面渲染。

二、react+redux实战

1.这里是我学习练习的一个小案例,框架使用create-react-app,请求的接口使用http://jsonplaceholder.typicode.com/posts

2.页面布局

页面上方是添加标题和内容的文本框,页面下方是请求接口的数据

3.主文件App.js

组件文件在components文件夹中,actions负责操作分发,reducers负责数据的处理,store.js负责

三、分步操作

1.Posts.js组件

fetch('http://jsonplaceholder.typicode.com/posts')

.then(res=>res.json())

.then(posts=>{

this.setState({

posts:posts

})

})

//通过请求获取数据渲染到页面

2.PostsForm.js组件

 //渲染功能

render() {

return (

<div>

<h1>添加内容</h1>

<form onSubmit={this.onSubmit}>

<div>

<label>title</label>

<br/>

<input type="text" name="title" onChange={this.onChange} value={this.state.title}></input>

</div>

<div>

<label>body</label>

<br/>

<textarea name="body" onChange={this.onChange} value={this.state.body}></textarea>

</div>

<br/>

<button type="submit">添加</button>

</form>

</div>

)

}

...

//绑定函数

onChange=(e)=>{

console.log(e.target)

this.setState({

[e.target.name]:e.target.value

})

}

onSubmit=(e)=>{

e.preventDefault()

const post = {

title:this.state.title,

body:this.state.body

}

}

//数据请求

fetch('http://jsonplaceholder.typicode.com/posts',{

method:'POST',

header:{

"content-type":"application/json"

},

body:JSON.stringify(postData)

})

.then(res=>res.json())

.then(data=>{console.log(data)}

)

3.初识store

1.npm i redux react-redux redux-thunk

2.使用redux是为了状态(数据)的统一管理,为了让所有组件拿到状态,需要使用<Provider></Provider>将根组件包裹

import {Provider} from 'react-redux'

function App() {

return (

<Provider store={store}>

<div className="App">

<PostForm></PostForm>

<Posts></Posts>

</div>

</Provider>

);

}

3.创建store, Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合而不是创建多个 store

import {createStore,applyMiddleware,compose} from 'redux'

import thunk from 'redux-thunk'

import rootReducer from './reducers/index'

const initialState = {}

const middleware = [thunk]

//createStore可以传三个参数:1.多个reducer对象;2.初始状态为空对象,当调用redux之后会返回一个新的对象;3.中间件applyMiddlewares是 Redux 的原生方法,作用是将所有中间件组成一个数组,依次执行

export const store = createStore(

rootReducer,

initialState,

applyMiddleware(...middleware)

)

4.Reducer和CombineReducers

1.Reducer

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

export default function(state=initialState,action){

switch(action.type){

default:

return state;

}

}

2.Reducer 的拆分

Reducer 函数负责生成 State。由于整个应用只有一个 State 对象,包含所有数据,对于大型应用来说,这个 State 必然十分庞大,导致 Reducer 函数也十分庞大,所以需要拆分Reducer。

//在创造store过程中rootReducer是多个对象

export const store = createStore(

rootReducer,

initialState,

applyMiddleware(...middleware)

)

3.CombineReducers

这样一拆,Reducer 就易读易写多了。而且,这种拆分与 React 应用的结构相吻合:一个 React 根组件由很多子组件构成。这就是说,子组件与子 Reducer 完全可以对应。

Redux 提供了一个combineReducers方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。

import {combineReducers} from 'redux'

import postReducer from './postReducer'

export default combineReducers({

posts:postReducer

})

5.actions和types

1.我们需要在actions文件夹里面定义操作的函数,然后在组件内进行调用。

重点:这一步就是将原本存在在组件中的操作(数据请求等)转移到actions中。组件调用actions中的方法就需要使用connect建立链接,React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。

import { connect } from 'react-redux'

import { fetchPosts } from '../actions/postActions'

const mapStateToProps = state => ({

posts:state.posts.items,

newPost:state.posts.item

})

export default connect(mapStateToProps,{fetchPosts})(Posts);

2.现在我们可以通过组件调用actions里面的方法

重点:redux需要actions的dispatch分发操作携带方法和store中的状态交给reducer进行处理,reducer返回更新后的状态(数据),组件进行更新。actions中有多种操作,所以在dispatch分发操作时需要配置action的types属性进行分辨执行哪个操作。

//创建types.js文件,types文件就是为不同action定义不同名字,需要在actions和reducers文件中引入,以便让reducer知道解决哪一种操作

export const FETCH_POSTS = "FETCH_POSTS";

export const NEW_POSTS = "NEW_POSTS";

3.

//postActions.js文件

export const fetchPosts = () => dispatch => {

fetch('http://jsonplaceholder.typicode.com/posts')

.then(res=>res.json())

.then(posts=>

// 当操作成功时,通过dispatch携带action.type和请求到数据给store,store告诉postReducer.js进行操作,返回处理后的状态

dispatch({

type:FETCH_POSTS,

payload:posts

})

)

}

//postReducer.js

export default function(state=initialState,action){

switch(action.type){

case NEW_POSTS:

return {

...state,

item:action.payload

}

case FETCH_POSTS:

return {

...state,

items:action.payload

}

default:

return state;

}

}

6.mapState获取最新状态

1.postReducer.js接收到action.type和请求到数据进行处理返回新的状态,这里reducer处理action操作得到的数据进行处理返回新的数据给store。

2.store中的数据更新,组件需要想办法进行接收。

mapStateToProps()是一个函数。它的作用就是像它的名字那样,建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系。

const mapStateToProps = state => ({

posts:state.posts.items

})

export default connect(mapStateToProps,{fetchPosts})(Posts);

3.另外redux要求我们需要给方法和状态规定数据类型

import PropTypes from 'prop-types'

//使用方法

Posts.proptypes = {

fetchPosts:PropTypes.func.isRequired,

posts:PropTypes.array.isRequired

}

7.添加数据

1.接收到文本框的数据PostForm.js

onSubmit=(e)=>{

e.preventDefault()

const post = {

title:this.state.title,

body:this.state.body

}

// 触发action

this.props.createPost(post)

}

2.PostActions.js接收到操作通知

export const createPost = postData => dispatch => {

fetch('http://jsonplaceholder.typicode.com/posts',{

method:'POST',

header:{

"content-type":"application/json"

},

body:JSON.stringify(postData)

})

.then(res=>res.json())

.then(post=>

// 当操作成功时,通过dispatch将数据和action.type交给postReducer.js处理

dispatch({

type:NEW_POSTS,

payload:post

})

)

}

3.postReducer.js根据对应的操作返回处理后的数据

export default function(state=initialState,action){

switch(action.type){

case NEW_POSTS:

return {

...state,

item:action.payload

}

case FETCH_POSTS:

return {

...state,

items:action.payload

}

default:

return state;

}

}

4.数据更改后,Post.js接收数据进行渲染

const mapStateToProps = state => ({

posts:state.posts.items,

newPost:state.posts.item //这里是添加的数据

})

写在最后

1.自认为redux比vuex复杂些,操作和数据类型要求的更规范些

2.官方将store中的数据定义为状态,状态改变即为数据更新,所以文章中有些地方使用状态和数据两种说明

3.使用redux后操作和数据请求不在组件中进行,而是交给actions和reducers,reducers将数据处理后返回给store,store通过mapStateToProps()方法将store中的数据对象和UI组件中的props进行映射,props改变导致页面进行重新渲染

建议:个人是初学者,很多地方描述不太准确。大家可以先看一下学习视频和阮一峰老师的博客,然后可以看一下我的文章,有什么不准确的地方可以留言说明。

以上是 react+redux实战——redux到底是个啥子? 的全部内容, 来源链接: utcz.com/z/382176.html

回到顶部