0

我正在使用 React Native 和 redux 开发一个应用程序。用于 Ajax 请求的 Express js。

我的 Ajax 请求中的数据不会加载,这是我收到的警告:

警告:setState(...):在现有状态转换期间无法更新(例如在render或其他组件的构造函数内)。渲染方法应该是 props 和 state 的纯函数;构造函数副作用是一种反模式,但可以移至componentWillMount.

不完全确定我做错了什么?

index.ios.js

import React, { Component } from 'react'

import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  NavigatorIOS
} from 'react-native'

import { Provider } from 'react-redux'
import store from './src/store'

import CategoryView from './src/category-view'

class myApp extends Component {
  render() {
    return (
      <Provider store={store}>
        <NavigatorIOS
          initialRoute={{
            component: CategoryView,
            title: 'myApp',
            index: 0
          }}
        />
      </Provider>
    );
  }
}

store.js

import { combineReducers, createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import category from './reducers/category'
import listings from './reducers/listings'

const reducers = combineReducers({
  category,
  listings
})

const initialState = {}

const store = createStore(
  reducers,
  initialState,
  applyMiddleware(
    thunkMiddleware
  )
)

export default store

这是我的视图文件:

import React from 'react'
import {
  View,
  ListView,
  ScrollView,
  StyleSheet,
  Image,
  TouchableHighlight
} from 'react-native'

import { connect } from 'react-redux'
import Listings from './listings'
import BetView from './bet-view'
import { getListings } from './actions/listings'

const getDataSource = (listings) =>
  (new ListView.DataSource({
    rowHasChanged: (r1, r2) => r1 != r2
  })).cloneWithRows(listings)

const _ListingsView = ({dataSource, navigator, onPress, onLoad}) => {
  onLoad()
  return(
    <ScrollView>
      <ListView
        dataSource={dataSource}
        renderRow={(row) =>
          <Listings
            teamOne={row.game[0]}
            teamTwo={row.game[1]}
            date={row.date}
            onPress={() => onPress(navigator, row.name)}
          />
        }
      />
    </ScrollView>
  )
}

const ListingsView = connect(
  (state) => {
    return {
      dataSource: getDataSource(state.listings.items || []),
      loading: state.listings.loading
    }
  },
  (dispatch) => {
    return {
      onPress: (navigator, name) =>
        navigator.push({
          title: 'test',
          component: BetView,
          passProps: {
            category: name
          }
        }),
      onLoad: () => dispatch(getListings())
    }
  }
)(_ListingsView)

export default ListingsView

动作文件:

const URL = 'http://localhost:3000/listings'

export const REQUEST_LISTINGS = 'request-listings'
export const RECEIVE_LISTINGS = 'receive-listings'

const requestListings = () =>
({
  type: REQUEST_LISTINGS
})

const receiveListings = (items) =>
({
  type: RECEIVE_LISTINGS,
  items: items || []
})

const shouldFetch = (state) => {
  const res = (!state.listings.items || 0 == state.listings.items.length && !state.listings.loading)
  return res
}

export const getListings = () =>
  (dispatch, getState) =>
    shouldFetch(getState())
    && dispatch(requestListings())
    && fetch(URL)
      .then(res => res.json())
      .then(json => dispatch(receiveListings(json)))

这是减速器:

import { RECEIVE_LISTINGS, REQUEST_LISTINGS } from '../actions/listings'

export default (state = {}, action) => {
  switch (action.type) {
    case RECEIVE_LISTINGS:
      return {
        loading: false,
        items: action.items
      }
    case REQUEST_LISTINGS:
      return {
        loading: true,
        items: []
      }
  }
  return state
}
4

1 回答 1

0

你可以尝试这样的事情。我还没有测试过。不确定它是否完美。但这就是想法

import React, {Component} from 'react'
import {
  View,
  ListView,
  ScrollView,
  StyleSheet,
  Image,
  TouchableHighlight
} from 'react-native'

import { connect } from 'react-redux'
import Listings from './listings'
import BetView from './bet-view'
import { getListings } from './actions/listings'

const getDataSource = (listings) =>
  (new ListView.DataSource({
    rowHasChanged: (r1, r2) => r1 != r2
  })).cloneWithRows(listings)

class _ListingsView extends Component {


  componentWillMount() {
    this.props.onLoad();
  }

  render() {
    return(
      <ScrollView>
        <ListView
          dataSource={this.props.dataSource}
          renderRow={(row) =>
            <Listings
              teamOne={row.game[0]}
              teamTwo={row.game[1]}
              date={row.date}
              onPress={() => this.props.onPress(this.props.navigator, row.name)}
            />
          }
        />
      </ScrollView>
    )
  }
}

const ListingsView = connect(
  (state) => {
    return {
      dataSource: getDataSource(state.listings.items || []),
      loading: state.listings.loading
    }
  },
  (dispatch) => {
    return {
      onPress: (navigator, name) =>
        navigator.push({
          title: 'test',
          component: BetView,
          passProps: {
            category: name
          }
        }),
      onLoad: () => dispatch(getListings())
    }
  }
)(_ListingsView)

export default ListingsView

所以你最好按照他们的例子:https ://facebook.github.io/react-native/docs/listview.html

或者这就是我在当前正在构建的应用程序中管理 ListViews 的方式: https ://github.com/kamiranoff/mythology/blob/master/src/components/HeroesList/HeroesList.js (在那个例子中它有点不同,因为甚至在这个组件被渲染和过滤列表之前就调用了 api,这就是为什么我在 componentWillReceiveProps 中更新数据源的状态)

于 2017-01-17T00:45:31.563 回答