reactnative - 15. Redux 重量级组件状态存储组件
访问量: 2058
参考: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