React Native:ListView在设置dataSource之前呈现

时间:2017-01-26 07:53:23

标签: javascript reactjs react-native

Listview尝试在设置数据源之前渲染(ComponentDidMount) 所以它总是空的。如果我尝试调用loadData(),它将显示它。

如何在加载完成之前避免组件渲染?

行动:

export const GET_COURSES = 'GET_COURSES';
export const GET_COURSES_FAILED = 'GET_COURSES_FAILED';

import getCoursesAPI from '../common/Functions';

export const getCourses = (users) => {
  return dispatch => {
    getCoursesAPI(users)
    .then((data)=>{
      const {courseList, lectureList} = data;
      return dispatch(coursesSuccess(courseList, lectureList));
    })
    .catch(()=>{
      return dispatch(coursesFailed());
    });
  };
}

const coursesSuccess = (courses, lectures) => {
  return {
    type: GET_COURSES,
    payload: {
      courses,
      lectures
    }
  }
};

const coursesFailed = () => {
  return {
    type: GET_COURSES_FAILED
  }
};

减速器:

import * as types from "./courses.actions";

export const INITIAL_STATE = {
  courses: {}
};

export default function courses(state = INITIAL_STATE, action){
  const {courses, lectures} = state;
  switch(action.type){
    case types.GET_COURSES:
    return {
      ...state,
      courses: action.payload.courses,
      lectures: action.payload.lectures
    };
    case types.GET_COURSES_FAILED:
    return {
      ...state,
      courses: courses ,
      lectures: lectures
    };
    default:
    return state;
  }
}

组件本身:

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

	constructor(props) {
      super(props);
      this.state = {
          dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
          }),
          dataLoaded: 0
      };
    }

	componentWillMount(){

	}

  componentDidMount(){
    this.props.getCourses(this.props.users);
  }

  componentWillReceiveProps(newProps) {
    const courses = newProps.courses.courses[this.props.user]
    this.setState({
        dataSource: this.state.dataSource.cloneWithRows(courses),
        dataLoaded: courses.length
    });
  }


	render() {
    return (
      <View style={{ height: Platform.OS == "ios" ? height - 114 : height - 130 }}>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={this.renderRow.bind(this)}
        />
      </View>
    );
	}
}

UPDATE @stinodes: enter image description here

这解决了问题,但我认为这不是正确的方法:

componentWillMount(){
    setTimeout(()=>{
      console.log('!run!');
      this.loadData();
    }, 1000);
	}

  componentDidMount(){

  }


  async loadData(){
    const {user, users, getCourses, courses} = this.props;
    await getCourses(users);
    const data = courses[user];
    this.setState({
      dataSource: this.state.dataSource.cloneWithRows(data),
      dataLoaded: data.length
    });
  }

1 个答案:

答案 0 :(得分:1)

您可以使用componentWillMount - 挂钩代替componentDidMount 使用第一个,在渲染之前设置它。后者在第一次渲染组件后触发。

编辑:由于您使用redux更新全局状态,然后将数据传递到道具中,因此您需要在组件安装时获取课程。您可以通过在componentDidMount - 挂钩中加载数据来实现此目的 但是,您不会需要async关键字,因为redux无论如何都会通过您的组件的道具传递课程。

当您的组件的道具更新时,它也会进行重新渲染。如果您希望自己的dataSource处于州内,可以使用componentWillReceiveProps - 挂钩。当您的组件收到新属性时,将触发此挂钩 调用此方法时,您可以将填充的数据源添加到您的状态。 赢了会导致新的渲染。

示例:

class Courses extends Component {
    /* ... */

    componentDidMount() {

        // Will fetch your data asynchronously
        this.props.getCourses(this.props.users);

    }

    // This hook gets the new props passed. Old props are
    // still available in this.props
    componentWillReceiveProps(newProps) {

        const courses = newProps.courses.courses[this.props.user]
        this.setState({
            dataSource: this.state.dataSource.cloneWithRows(courses),
            dataLoaded: courses.length
        })

    }

    /* ... */
}