【问题标题】:React Native with Redux : data is loaded, render shows emptyReact Native with Redux:数据已加载,渲染显示为空
【发布时间】:2017-02-02 08:07:59
【问题描述】:

我有一个带有 react-redux 、 redux-persist 和 redux-thunk 的 react native 应用程序。

在组件中,我正在从 props 中渲染数据,如果数据长度小于 1,我会显示错误,没有可用数据。

它总是显示“没有可用数据”,但实际上数据在道具中。当我检查控制台日志时,(使用 redux-logger )数据在道具中可用。

如果我将forceUpdate() 放在componentDidMount 上甚至没有帮助。

但如果我将forceUpdate() 设置为超时,它将加载数据。

setTimeout(()=>{
      this.forceUpdate();
    }, 1000);

可能是什么问题?渲染是否在从道具加载数据之前发生? CoursesPage.js

import {bindActionCreators} from "redux";
import {connect} from "react-redux";
import Courses from "./components/Courses";
import {Actions as routes} from "react-native-router-flux";
import * as courseActions from "./courses.actions";

function mapStateToProps(state) {
	return {
		user: state.auth.user,
		users: state.auth.users,
		courses: state.courses.courses,
		lectures: state.courses.lectures,
		courseDetails: routes.courseDetails,
		openProfile: routes.profilePage
	}
}

function dispatchToProps(dispatch) {
	return bindActionCreators({
		getCourses: courseActions.getCourses
	}, dispatch);
}

export default connect(mapStateToProps, dispatchToProps)(Courses);

课程.js

import React, {Component, PropTypes} from "react";
import {
  ActivityIndicator,
  ListView,
  StyleSheet,
  Text,
  View,
  Image,
  NetInfo,
  Alert,
  TouchableOpacity,
  ScrollView,
  Dimensions,
  Platform,
  RefreshControl
} from 'react-native';
import { Loader, Accordion, I18n, CustomNavBar, CustomAccordion } from "../../common/components";
import styles from "../../common/styles";
let DeviceInfo = require('react-native-device-info');
import Icon from 'react-native-vector-icons/Ionicons';
let { width, height } = Dimensions.get('window');

export default class Courses extends Component {
	static propTypes = {
		user: PropTypes.string.isRequired,
    users: PropTypes.object.isRequired,
		courseDetails: PropTypes.func.isRequired,
		courses: PropTypes.object.isRequired,
    getCourses: PropTypes.func.isRequired,
    openProfile: PropTypes.func.isRequired
	};

	constructor(props) {
    super(props);
    this.state = {
      isLoading: false,
      isRefreshing: false
    };
    this._isMounted = false;
  }

	componentWillMount(){
    this._isMounted = true;
    const { users, getCourses } = this.props;
    getCourses(users);
	}

  componentWillUnmount(){
    this._isMounted = false;
  }

  componentWillReceiveProps(){
    setTimeout(()=>{
      this.forceUpdate();
    }, 1000);
  }

  componentDidMount(){
    setTimeout(()=>{
      this.forceUpdate();
    }, 1000);
    setTimeout(()=>{
      this.forceUpdate();
    }, 2000);
  }

  async loadData(){
    await this.props.getCourses(this.props.users);
    setTimeout(()=>{
      this.forceUpdate();
    }, 1000);
  }

  selectRow(courseData) {
    this.props.courseDetails({
      courseData: courseData
    });
  }

  renderData(containerList){

    /*  rendering .... */
  
  }

	render() {
    const {user, users, getCourses, courses, openProfile} = this.props;
    const data = courses[user];
    let containerList = [];
    Object.keys(data).forEach((d)=>{
      let courseList = [];
      Object.keys(data[d].courses).forEach((c)=>{
        courseList.push(data[d].courses[c]);
      });
      containerList.push({
        id: data[d].id,
        title: data[d].title,
        courses: courseList
      });
    });

    return (
        <View style={styles.container}>
          <View style={{ width: width, height: Platform.OS == "ios" ? 64 : 54}}>
            <CustomNavBar
              width={width}
              height={Platform.OS == "ios" ? 64 : 54}
              title={I18n.t("details_page_book_button")}
              titleSize={18}
              buttonSize={15}
              background={"#00a2dd"}
              color={"#FFF"}
              rightIcon={"ios-person-outline"}
              rightIconSize={30}
              rightAction={()=> { openProfile(); }}
            />
          </View>
          <View style={{ height: Platform.OS == "ios" ? height - 114 : height - 130 }}>
            {!this.state.isLoading ?
              <ScrollView
              refreshControl={
                <RefreshControl
                  refreshing={this.state.isRefreshing}
                  onRefresh={this.loadData.bind(this)}
                  tintColor="#00a2dd"
                  title=""
                  titleColor="#00a2dd"
                  colors={['#00a2dd', '#00a2dd', '#00a2dd']}
                  progressBackgroundColor="#FFFFFF"
                />
              }
            >
              {this.renderData(containerList)}
            </ScrollView>
            :<ActivityIndicator
        				animating={true}
        				style={{ paddingTop: Platform.OS == "ios" ? (height - 114)/2 : (height - 130)/2 }}
        				color={'#00a2dd'}
        				size={'small'}
        			/>}
          </View>
        </View>
    );
	}
}

【问题讨论】:

  • 你能在ComponentWillMount生命周期方法中访问props吗?我的意思是来自redux 的道具的价值是什么?
  • @Yaseminçidem 我可以访问组件中的道具将挂载,但并非所有数据都在那里。请参阅有问题的屏幕截图。我已经更新了问题。
  • 你在这里的目标是什么const { users, getCourses } = this.props;getCourses(users);是你的操作方法getCourses?如果是,如果你用this.porps.actions.getCourses更改代码以访问操作
  • getCourses 是一个动作。查看更新的代码@Yaseminçidem

标签: reactjs react-native react-redux redux-thunk


【解决方案1】:

我认为你不改变状态,所以看到相同的数据。所以我建议你应该像下面这样改变代码。另外你应该不可变的 js 来改变状态。

课程操作

export function getCoursesRequest () {
  return {
    type: "GET_COURSES_REQUEST"
  }
}
export function getCoursesSuccess (json) {
  return {
    type: "GET_COURSES_SUCCESS",
    payload: json
  }
}
export function getCoursesFailure (json) {
  return {
    type: "GET_COURSES_FAILURE",
    payload: json
  }
}
export function getCourses (sessionToken) {
  return dispatch => {
    dispatch(getCoursesRequest())
    // store or get a sessionToken
    return appAuthToken.getSessionToken(sessionToken)
      .then((token) => {
        return BackendFactory(token).getCourses()
      })
      .then((json) => {
        dispatch(getCoursesSuccess(json))
      })
      .catch((error) => {
        dispatch(getCoursesFailure(error))
      })
  }
}

coursesInitialState

const {Record} = require("immutable");

var InitialState = Record({
    courses: {}
});
export default InitialState;

减速器

const InitialState = require("./authInitialState").default;    

const initialState = new InitialState();

export const courseReducer = (state = initialState, action) => {
    if (!(state instanceof InitialState)) return initialState.mergeDeep(state);
    switch (action.type) {

        case "GET_COURSES_SUCCESS":
            const {value} = action.payload;
            let nextState = state.setIn(["courses"], value;

            return nextState;
        case "GET_COURSES_FAILURE":
    }
}

【讨论】:

  • 感谢您的回答。我试试看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多