react + redux大体思路(二)

实例

在/app/host/components/houses/house_list.js文件中:

import React, {Component} from 'react';
import {StyleSheet, View, Text, Image, ListView, ScrollView, TouchableWithoutFeedback,TouchableOpacity} from 'react-native';

import {I18n, S, COLOR} from '../../utils/tools'
import RightAddBarButton from '../common/navigatorBar/rightAddBarButton'
import NavigationBar from 'react-native-navbar'
import HouseResource from './house_resources'
import Loading from '../loading'
import HouseManagePopup from '../helpPopup/house_manage_popup'
import RefreshInfiniteListView from '../refresh_infinite_list_view'
import HouseNothing from './house_nothing'

const ds = new ListView.DataSource({
  rowHasChanged: (row1, row2) => row1 !== row2
})

export default class HouseList extends Component {

  static contextTypes = {
    page: React.PropTypes.object
  };

  constructor(props) {
    super(props)
  }

  componentDidMount() {
    const {actions} = this.props
    actions.fetchRoomsIfNeeded({page:1})
  }

  render() {

    let titleConfig = {
      title: I18n.t('house.house_manage'),
    }
    return(
      <View style={[S.container, {backgroundColor: '#ededed'}]}>
        <NavigationBar title={titleConfig}
          rightButton = {<RightAddBarButton onPress = {() => this._onPress()}/>} />
          {this._renderContent()}
      </View>
    )
  }

  _renderContent() {

    var data = this.props.rooms.houses.items
    var status = this.props.rooms.houses.status
    let paging = this.props.rooms.houses.paging

    if (status == 0) {
      return (
        <Loading/>
      )
    } else {
      if (status == 200 && paging.total_pages == 0 || data.length == 0) {
        return(
          <View>
            <HouseNothing />
              <TouchableOpacity onPress={()=>this.onRefresh()}>
              <View style={{alignItems:'center',height: 50,marginTop: 40}}>
                <Text style={{fontSize: 14}}>{I18n.t(`common.retry`)}</Text>
              </View>
              </TouchableOpacity>
          </View>
        )
      } else {
        return (
          <RefreshInfiniteListView
            ref={(list) => {this.list = list}}
            customize={true}
            initialListSize={10}
            dataSource={ds.cloneWithRows(data)}
            renderHeader={() =>this._listHeader()}
            renderRow={(rowData) => this._houseRenderRow(rowData)}
            renderSeparator={this.renderSeparator}
            scrollEventThrottle={10}
            loadedAllData={() => this.loadedAllData()}
            onInfinite={() => this.onInfinite()}
            scrollEventThrottle={10}
            onRefresh={() => this.onRefresh()}
          >
          </RefreshInfiniteListView>
        )
      }
    }
  }

  onRefresh() {

    const {actions} = this.props
    actions.fetchRoomsIfNeeded({page:1})

  }

  loadedAllData() {
    let paging = this.props.rooms.houses.paging
    if (paging && paging.current_page && paging.total_pages) {
      return paging.current_page >= paging.total_pages
    }
  }

  onInfinite() {
    const { actions } = this.props
    var page = this.props.rooms.houses.paging.current_page
    actions.fetchRoomsIfNeeded(
      {
        page: page + 1,
        success: () => {
          this.list.hideFooter()
        }
      }
    )
  }

  _listHeader() {
    return(
      <TouchableWithoutFeedback onPress={()=>this._house_manage_popup()}>
        <View style={styles.header}>
          <Text style={{marginRight: 5}}>{I18n.t('house.house_manage')}</Text>
          <Image source = {require('./img/help_ic.png')}/>
          {this._manage_popup()}
        </View>
      </TouchableWithoutFeedback>
    )
  }

  _manage_popup(){
    return(
      <HouseManagePopup ref={(c) => this.HouseManagePopup = c} />
    )
  }

  _house_manage_popup(){
    this.HouseManagePopup.openPopup();
  }

  _houseRenderRow(rowData) {
    var house = this.props.rooms.data[`${rowData}`]
    var dataArray = this.props.rooms.houses.data[`${rowData}`]
    var rooms=[]

    if (!_.isEmpty(dataArray)) {
      _.map(dataArray,(element,index)=>{
        var roomsMessages = this.props.rooms.data[`${element}`]
        rooms.push(roomsMessages)
      })
    }
    return(
      <View>
        <View style={[styles.cell,styles.border]}>
          <HouseResource house={house} rooms={rooms} number={rowData}/>
        </View>
      </View>
    )
  }

  renderSeparator() {
    return (
      <View></View>
    )
  }

  _onPress() {
    this.context.page.navigator.push({
      id:'house_publish',
    });
  }
}

var padding = 10
const styles = StyleSheet.create({
  cell:{
    marginLeft: padding,
    marginRight: padding,
    marginBottom: padding,
    backgroundColor: '#fafafa',
  },
  border: {
    borderRadius: 2,
    borderWidth:0.5,
    borderColor:'#cdcdd3',
    shadowRadius: 2,
    shadowOpacity: 0.02,
    shadowOffset: {
      height: 1
    }
  },
  header: {
    marginLeft: padding,
    marginRight: padding,
    marginTop: 5,
    marginBottom: 5,
    justifyContent: 'flex-end',
    flexDirection: 'row',
  },
});
HouseList即是整个一个界面的组件

static contextTypes = {

page: React.PropTypes.object

};

这段函数是从最父组件/app/modal_container.js中以下这句继承而来:

childContextTypes: {

app: React.PropTypes.object,

page: React.PropTypes.object,

},

componentdidmount是render执行完后的回调函数

componentDidMount() {

const {actions} = this.props

actions.fetchRoomsIfNeeded({page:1})

}

整个过程是render执行{this._renderContent()}这个_render_Content()方法,render完全执行完之后执行ComponentDidMount这个回调函数, 然后再顺着ComponentDidMount()以后的东西, 也就是再执行一边render中的东西, 也就是渲染页面。

但回到ComponentDidMount()回调函数中的actions.fetchRoomsIfNeeded({page:1})

这个action在/app/host/actions/roomsActions.js中:

export function fetchRoomsIfNeeded(params = {}) {
  return (dispatch, getState) => {
    if (shouldFetchRooms(getState(),params)) {
      return dispatch(fetchRooms(params, refresh = false))
    }
  }
}
getState()为得到所有的整棵树, params即为上面函数中传进来的{page: 1}

先执行shouldFetchRooms(getState(),params)

function shouldFetchRooms(state, params) {
  const houses = state.rooms
  if (houses <= 0) {
    return true
  } else if (houses.isFetching) {
    return false
  } else {
    return true
  }
}
判断一些存在的值, 来验证, 然后执行 dispatch(fetchRooms(params, refresh = false))

先执行fetchRooms(params, refresh = false)

function fetchRooms(params) {
  return (dispatch) => {
    dispatch(requestRooms(params))
    return Octopus.fetch({url: `/v1/houses.json`, body: {page:params.page}})
      .then(response => response.json())
      .then(responseData => {
        if (responseData.meta.status == 403) {
          dispatch({type: types.NEED_LOGIN, params: params})
        } else {
        dispatch(receiveRooms(params, responseData))
        params.success && params.success(responseData.data)
      }
    })
    .catch(reason => {
      __LOG.info(` ${reason} ............................... `)
    })
  }
}
先执行requestRooms(params)
function requestRooms(params) {
  __LOG.info(`  start  fetchMessages  ---------------- `)

  return {
    type: types.REQUEST_ROOMS,
    params: params
  }
}
这个里面基本做一些数据的验证, 所以先不看
return Octopus.fetch({url: `/v1/houses.json`, body: {page:params.page}})这句是请求url并带着参数, 成功的话执行dispatch(receiveRooms(params, responseData))
receiveRooms(params, responseData)这个函数是
function receiveRooms(params, responseData) {
  return {
    type: types.RECEIVE_ROOMS,
    rooms: responseData.data.houses,
    paging: responseData.meta.paging,
    status: responseData.meta.status,
    params: params,
    receivedAt: Date.now()
  }
}
/app/host/actions/actionTypes.js这个文件中找action和reducer的对应关系(当然如果写的时候这里也要注册)
跳到相应type的reducer中/app/host/reducers/rooms.js
    case types.RECEIVE_ROOMS:
    var{data,houses}=state
    var dataArray = data
    var housesData=houses.data
    var itemsArray=houses.items

      action.rooms.forEach((item, index) => {
        var housesArray=[]
        _.uniq(itemsArray.push(item.number))

        if (!_.isEmpty(item.roomings)) {
          var roomArray=[]
          item.roomings.forEach((element,index)=>{
            dataArray[`${element.number}`]=element
            _.uniq(housesArray.push(element.number))
          })
          housesData[`${item.number}`]=housesArray
          dataArray[`${item.number}`]=_.omit(item,'roomings')
        }else {
          dataArray[`${item.number}`]=item
          housesData[`${item.number}`]=[]
        }

      })
      houses = Object.assign({},houses, {
                isFetching: false,
                items:_.uniq(itemsArray),
                data: housesData,
                paging: action.paging,
                query: {},
                status: action.status,
              })
      return Object.assign({}, state, {data: dataArray,houses:houses})

    break;
对数据进行处理和合并到State大树中, 
action.paging即为action中最后执行dispath函数return所稍带的参数


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值