reactnative - 15. Redux 重量级组件状态存储组件
访问量: 2095
参考:https://redux.js.org/introduction/getting-started
redux 是 react团队开发的: 可预测的保存状态的容器。(predictable state container for js app)
这句话非常拗口。
举个例子:
我们在登录页面点击 发送 短信验证码,按照1分钟倒计时的话,无论我们跳转到哪个其他的页面,再跳转回来,都应该可以看到这个页面的倒计时在不断的下降。 这个倒计时是不收页面的各种刷新的影响的。
这个就是一种“状态” (state)
也可以简单的认为, redux就是vuejs中的vuex , 是一种很高级的存储类库。
安装:
$ npm install --save redux
store: 保存data ,
reducer: 是store的参数。 是一个function .用来“变换” store中的数据
actionCreator: 该方法返回的值, 就是store.dispatch()的参数
redux 对于异步的操作,是需要通过中间件来完成的,使用的时候,跟同步的效果是一样的。
store发生变化之后,可以使用subscribe来通知:
// 就是通过这个方法来感知某个store发生了变化
// 这里的subcribe 应该重命名成: notify
store_0.subscribe(function(){
console.log('== store_0 has been updated, new state: ', store_0.getState())
})
React Native 中的用法:读取数据,并更新页面状态(计数器,点一下两秒后改变,并刷新页面)
React Native 中使用 redux
参考:https://appdividend.com/2018/08/04/react-native-redux-example-tutorial/?bs-comment-added=1#comment-20105 (单页面中使用 ) 和
https://moduscreate.com/blog/react-navigation-redux-in-react-native-applications/ (StackNavigator中使用)
1. 安装第三方包
npm install redux react-redux --save
2. 增加首页入口,路由。
修改 Home.js, App.js ,过程略。
3. 增加骨架文件:screens/ReduxDemo.js
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
export default class ReduxDemo extends Component{
constructor(props){
super(props)
}
render(){
return(
<View>
<Text>本例子演示Redux在React Native中的使用: 保存数据和状态。 {"\n"}
1. 点击之后,计数器 + 1 {"\n"}
2. 点击之后,5秒内 按钮不可点击 。
</Text>
<Button
title="点击计数!"
onPress={ () => {
// do nothing
}}
/>
</View>
)
}
}
然后,分别建立: reducer, => store => connect
建立reducer:
新建文件夹: redux_demo, 然后在其中:
1. 新建 types.js
export const INCREASE_COUNT = 'INCREASE_COUNT'
2. 新建 action creator.js:
import { INCREASE_COUNT } from './types'
export const increaseCount = (para) => {
// type 参数是必须有的, 其他的可以自行填写。这里就是一个 填参数的过程。
return {
type: INCREASE_COUNT
}
}
3. 新建 reducers.js
import { INCREASE_COUNT} from './types'
const initialState = {
count: 0
// isClickable: true
}
const countReducer = (state = initialState, action ) => {
switch(action.type) {
case INCREASE_COUNT:
console.info("== count: ", state.count)
return {
// ...state,
count: state.count + 1 // 我们只关心这一个就好了。
}
default:
return state
}
}
export default countReducer
4. 建立store.js
import {createStore, combineReducers} from 'redux'
import countReducer from './reducers'
const rootReducer = combineReducers({
countReducer: countReducer
})
const configureStore = () => {
return createStore(rootReducer)
}
export default configureStore
5. 修改 入口文件 index.js
/** @format */
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
// 以下为 为调用Redux 而新增的代码
// 这句话虽然没有被显示调用,但是不加会报错, 在 const myProvider那里。
import React from 'react'
import configureStore from './redux_demo/store'
import { Provider } from 'react-redux'
const store = configureStore()
const myProvider = () => {
// 这里要记得使用 return , 否则会报错:
// 网上这个例子是错的:
// 参考:https://stackoverflow.com/questions/49075731/invariant-violation-app-nothing-was-returned-from-render-this-usually-me?rq=1
return(
<Provider store = {store} >
<App />
</Provider>
)
}
AppRegistry.registerComponent(appName, () => myProvider);
6. 修改 对应的页面文件: ReduxDemo.js
import React, { Component} from 'react';
import {Image, Platform, StyleSheet, Text, View, Button} from 'react-native'
// 1. 导入相关的文件
import {connect } from 'react-redux'
import {increaseCount} from '../redux_demo/action_creators'
class ReduxDemo extends Component{
// 4. 定义被触发的事件。
clickButton = () => {
// 4.1 该方法来自于下面的 mapDispatchToProps
// 在 6.2 步骤中
this.props.increaseCountByOne()
}
render(){
return(
<View>
<Text>本例子演示Redux在React Native中的使用: 保存数据和状态。 {"\n"}
1. 点击之后,计数器 + 1 {"\n"}
</Text>
{ /* 3. 在 View中增加对应的事件。 */}
<Button
title="点击计数!"
onPress={this.clickButton}
/>
<Text>
您点击了:{this.props.count} {"\n"} (请使用 根目录下的 "AppWithRedux.js "进入到本页面。 否则页面看不到效果。(只能在console 中看到效果) )
</Text>
</View>
)
}
}
// 5. 把state 映射到 props中。
const mapStateToProps = state => {
return {
// 5.1 务必注意,这里是 store.countReducer.count 不是 state.count
// 没有为什么,把他背下来。
count: state.countReducer.count
}
}
// 6. 把 dispatch 映射到 props中
const mapDispatchToProps = dispatch => {
return {
// 6.1 定义了一个方法,该方法会在 Component中被调用
increaseCountByOne: () => {
// 6.2 increaseCount() 方法来自于 action_creators.js中定义的
dispatch(increaseCount())
}
}
}
// 7. 让上面两个映射生效。 废代码,没意义,但是没它不行。 就得这样写。
export default connect(mapStateToProps, mapDispatchToProps)(ReduxDemo)
这个时候,就可以在Android console 中看到效果了。 (数据已经被保存)
12-29 16:52:46.418 2502-3671/com.hello I/ReactNativeJS: '== count: ', 0 12-29 16:52:47.079 2502-3671/com.hello I/ReactNativeJS: '== count: ', 1 12-29 16:52:47.273 2502-3671/com.hello I/ReactNativeJS: '== count: ', 2 12-29 16:52:47.418 2502-3671/com.hello I/ReactNativeJS: '== count: ', 3 12-29 16:52:47.584 2502-3671/com.hello I/ReactNativeJS: '== count: ', 4 12-29 16:52:47.715 2502-3671/com.hello I/ReactNativeJS: '== count: ', 5
在页面上也 可以看到,每点击一下, 数字就+1