react-native 之 state 和 props 以及 redux 和 react-redux

Component 中 state 和 props 的区别;

组件Component中状态state和属性props的区别

stateprops
state是在组件内部定义的一个特殊对象{}
既起到组件内部的一种缓存作用,
也具备由于state变化而激发生命周期中渲染的方法
render()被回调的作用。且使用域仅限于组件内部。
props是组件属性,连接了外部父组件和组件内部的使用域。
它的改变激发声明周期方法componentWillReceiveProps(nextProps)
和渲染的方法render()逐次被回调。连接外部父组件,
可以通过父组件向其传递value、function等,连接内部组件,
this.props缓存了当前组件的所有props属性内容
{value, function}=this.props;

代码解释 props

 /**
   * 通过封装 FlatList 自定义一个列表组件
   */
export default class MyFlatList extends Component {
    constructor(props) {
        super(props);

    }

   ...
    /**
     *象组件FlatList中的
     *ref、ListHeaderComponent、ItemSeparatorComponent、
     *data、keyExtractor、onRefresh、refreshing等都是props属性;
     *
     * 象这种样式的定义 this.props.itemSeparator、
     * this.props.onRefresh、this.props.refreshing、this.props.onLoadMore等
     * 属于自定义组件MyFlatList的属性,是我们依照FlatList所定义的。
     * 类似象外部开放的接口一样,就像这里FlatList使用自己的
     * 属性ListHeaderComponent、ItemSeparatorComponent、data等一样来使用;
     * @returns {XML}
     */
    render() {
        return (<View style={{flex: 1, backgroundColor: Colors.bg}}>
            <FlatList
                ref={(flatlist) => this.flatlist = flatlist}
                ListHeaderComponent={this._header} 
                renderItem={this._renderItem}
                ItemSeparatorComponent={this.props.itemSeparator}
                data={this.props.data}
                keyExtractor={this._keyExtractor}
                onRefresh={this.props.onRefresh}
                refreshing={this.props.refreshing}
                onEndReachedThreshold={0.1}
                onEndReached={this.props.onLoadMore}
                initialNumToRender={3}
                getItemLayout={(data, index) => ({
                length: 250, offset: (250 + 10) * index, index
                })}
            />
        </View>);
    }
}

这是使用MyFlatList,来看下它的这个props

export default class FlatlistScreen extends Component {
 ...
    /**
     *这里MyFlatList的 itemSeparator、data、onRefresh 、refreshing 、onLoadMore 
     *就是FlatList中使用this.props.xxx来定义的。 
     * @returns {XML}
     */
    render() {
        return (<View style={styles.container}>
           ...
            <MyFlatList
                {...this.props}
                itemSeparator={() => this.separator()}
                data={this.state.dataSource}
                onRefresh = {()=>this.onRefresh()}
                refreshing = {this.state.isRefresh}
                onLoadMore = {()=>this.onLoadMore()}
            />
        </View>);
    }
}

除了以上,如果是对数据内容的props属性的变化,如上面代码的data变化,必然会激发MyFlatList组件生命周期方法componentWillReciveProps回调,这里我们可以在render方法回调前,对数据再次进行判断处理。
**这就是props属性功能和作用!!**

代码解释 state

export default class FlatlistScreen extends Component {
    constructor(props) {
        super(props);
        this.unmount = false;
        this.state = ({
            dataSource : [],
            isRefresh: true,
        });
    }
    ...
    /**
     * 功能:使用箭头函数,不使用bind;因为bind函数每调用一次就会创建一个新的函数
     */
    onRefresh() {
        this.setState({
            isRefresh: true,
        });

        //功能:制造刷新效果
        this.interval = setInterval(() => {
            clearInterval(this.interval);
            //功能:制造上拉加载更多的效果
            const data = [];
            for (let i = 0; i < 8; i++) {
                data.push({id: i, title: '亲子旅游日带娃儿玩' + i + '折起', state: '已过期', date: '2018/06/0' + (i - 8)},)
            }
            this.setState({
                dataSource: data,
                isRefresh: false,
            });

        }, 2000)
    }

   ...

    render() {
        return (<View style={styles.container}>
           ...
            <MyFlatList
                {...this.props}
                itemSeparator={() => this.separator()}
                data={this.state.dataSource}
                onRefresh = {()=>this.onRefresh()}
                refreshing = {this.state.isRefresh}
                onLoadMore = {()=>this.onLoadMore()}
            />
        </View>);
    }
}

看构造方法这里

this.state = ({
            dataSource : [],
            isRefresh: true,
        });

这就是state的定义方式。通过改变dataSourceisRefresh的值就能激发render再次渲染组件。
比如这里的onRefresh方法使用了

 this.setState({
      dataSource: data,
      isRefresh: false,
 });

来控制改变state的时机,来控制组件渲染的时机。
**这就是状态state的使用!!**


react-native 与 Redux 的配合使用;

Redux使用中,一些必知的概念

Reduxstateactionreducers
Redux 是 JavaScript 状态容器,
提供可预测化的状态管理。
使用 Redux 的一个益处,
就是它让 state 的变化过程变的可预知和透明。
以一个对象树的形式储存在于一个单一的 store 中,
惟一改变 state 的办法是触发 action。
一个描述发生什么的指示器对象。
action 内必须使用一个字符串类型的 type 字段,
来表示将要执行的动作。
且应该尽量减少在 action 中传递的数据;
描述 action 如何改变 state 树。
reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。

这里是我基于Redux实现的已给简单操作流程源码
结合源码+图例,分析下redux的执行操作流程,解读redux是怎样原理!

登录操作执行图

现在定位在登录页面,处于未登录状态,需要点击登录操作。
这里写图片描述

图并结合源码分析

登录页面的部分源码,展示了登录页面的UI
这里写图片描述
从源码中50行看到,点击登录按钮,则调用方法login() ,而login()这个方法是从this.props中解构赋值拿出来的,就是源码37行所示。
疑问1? this.props中的login()是从哪里来的,怎么会在this.props中?!
接着看同一js文件中的代码片段
这里写图片描述
这里有一个方法非常的重要connect(),她是干什么的,这里可以解答。
简单的说是,就我们所看到的代码从64到74行,connect()里面有两个回调函数,第一个回调的是state(Login页面的state),第二回调的是dispatch(Login页面用来进行分发登录操作的Action)。通过connect()()实现了 回调函数中 status、isSuc、user 和 login() 他们与当前的组件(登录页面)的this.props绑定,也就是他们被注入到了this.props中。
所以,点击登录的执行流程是这样的:
点击登录按钮——>调用this.props中的login方法——>派发登录操作的action ——>.. reducer处理…导致store的state树中登录组件的state发生变化 … ——>源码中65行执行回调,同时UI将会执行重新的刷新、渲染——>渲染过程中需要的内容,从回调中的state中获取、赋值。

继续深入…
登录功能的Action中有两类内容,一是需要传递的用户数据对象
这里写图片描述
二是派发的Action构建函数
这里写图片描述
图中可以清晰看到,Action有两种实现方式,其中最后一种是异步的Action构建函数,前面则是同步的Action构建函数;通常异步的Action中会调用同步的Action。而同步的Action有一个特点就是有一个约定成俗的字段叫type,标识着Action的通知类型。
当执行登录操作,使用redux进行登录操作的action进行派发的时候,调用了异步的Action,异步的通知由在内部执行异步操作,调用同步的action。执行到这里,action就会被分发到哪里呢??reducer
reducer也分为两部分,一是登录页面内容展示登录组件的state
这里写图片描述
是一个登录操作在执行到reducer时的处理,进行复制、赋值、填充的state模型的数据对象,store树中的一个对象。
reducer的处理也很简单,就是根据action的指定处理方式type,进行处理。处理完成之后,返回一个新的state对象。看源码是不是这样的?!
这里写图片描述

执行处理到这里,想到你已经发起疑问了。疑问2?总觉得,到reducer处理之后与组件容器那儿回调,直到页面再次渲染,没有什么关联??!它们到底是怎么建立关系的呢?
当然是通过Redux,以及处理异步action需要用到的中间件(标准的做法是使用 Redux Thunk 中间件)。
看这里,首先是集合管理action的处理,对reducer的管理
这里写图片描述
然后把对reduer的管理,以及处理结果再交给redux
这里写图片描述
并且也同时,把上面的两个reduer对应的处理结果state,作为store树的分支,绑定到了store中,进行统一管理和处理。而且还有一点很关键、很重要!也是急需解决的重要疑问——store树长什么样子?? 经过我的实践和测试对比得出结论, store树 中的登录组件的state,其数据内容的样子是和上图中源码第10行 rootReduer 中的数据结构LoginIn是对应的。也就是说他们是互相映射的。即, store与rootReduer 在数据结构上是一致的, store树 就是通过这样的rootReduer 中一条条 {key:value} 数据拼凑到一起所组成的对象。如果有点疑问,自己可以动手试一试,并用下图再加深下印象
这里写图片描述
store树是用来管理组件state数据的,好,因为我们使用了全局提供store的方式进行了处理,这里写图片描述
store中的属性,我们可以在项目中进行全局使用。
所以,在connect()()代码块中,当state发生变化,产生回调,我们可以通过state.LoginIn.status、state.LoginIn.isSuc、state.LoginIn.user来指定拿到当前组件对应的state数据。而state.LoginIn的调用方式就是从store树中取出LoginIn对应的state,而LoginIn是哪来的?也许内容有点多,蒙圈了,其实就在原先这里第11行代码。
这里写图片描述
所以,我之前总结的结论,store树中的登录组件的state,其数据内容的样子是和上图中源码第10行rootReduer中的数据结构LoginIn是对应的。也就是说他们是互相映射的。 store与rootReduer 在数据结构上是一致的, store树 就是通过这样的rootReduer 中一条条 {key:value} 数据拼凑到一起所组成的对象。是正确的!到这里则回答了上面的疑问2?,同时也解决了Redux的使用以及执行原理。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
react-native-redux-router是一个用于在React Native应用中管理路由和状态的库。它结合了React Native、Redux和React Navigation,提供了一种方便的方式来处理应用程序的导航和状态管理。 下面是一个简单的示例,演示了如何在React Native应用中使用react-native-redux-router: 1. 首先,安装所需的依赖项。在终端中运行以下命令: ```shell npm install react-native react-redux redux react-navigation react-native-router-flux --save ``` 2. 创建一个Redux store,并将其与React Native应用程序的根组件连接起来。在App.js文件中,添加以下代码: ```javascript import React from 'react'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import rootReducer from './reducers'; import AppNavigator from './navigation/AppNavigator'; const store = createStore(rootReducer); export default function App() { return ( <Provider store={store}> <AppNavigator /> </Provider> ); } ``` 3. 创建一个导航器组件,并定义应用程序的导航结构。在navigation/AppNavigator.js文件中,添加以下代码: ```javascript import { createAppContainer } from 'react-navigation'; import { createStackNavigator } from 'react-navigation-stack'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { Actions } from 'react-native-router-flux'; import HomeScreen from '../screens/HomeScreen'; import DetailsScreen from '../screens/DetailsScreen'; const MainNavigator = createStackNavigator({ Home: { screen: HomeScreen }, Details: { screen: DetailsScreen }, }); const AppNavigator = createAppContainer(MainNavigator); const mapStateToProps = state => ({ // 将Redux状态映射到导航器组件的props中 }); const mapDispatchToProps = dispatch => bindActionCreators(Actions, dispatch); export default connect(mapStateToProps, mapDispatchToProps)(AppNavigator); ``` 4. 创建屏幕组件,并在其中使用导航和Redux状态。在screens/HomeScreen.js文件中,添加以下代码: ```javascript import React from 'react'; import { View, Text, Button } from 'react-native'; import { Actions } from 'react-native-router-flux'; const HomeScreen = () => { return ( <View> <Text>Welcome to the Home Screen!</Text> <Button title="Go to Details" onPress={() => Actions.details()} /> </View> ); } export default HomeScreen; ``` 5. 创建其他屏幕组件,并在其中使用导航和Redux状态。在screens/DetailsScreen.js文件中,添加以下代码: ```javascript import React from 'react'; import { View, Text, Button } from 'react-native'; import { Actions } from 'react-native-router-flux'; const DetailsScreen = () => { return ( <View> <Text>Welcome to the Details Screen!</Text> <Button title="Go back" onPress={() => Actions.pop()} /> </View> ); } export default DetailsScreen; ``` 这是一个简单的示例,演示了如何在React Native应用中使用react-native-redux-router来管理路由和状态。你可以根据自己的需求进行扩展和定制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值