简体   繁体   English

React Native:ListView在设置dataSource之前渲染

[英]React Native: ListView renders before dataSource being set

Listview tries to render, before the datasource is set (ComponentDidMount) So it's always empty. 在设置数据源(ComponentDidMount)之前,Listview尝试渲染。因此它始终为空。 if i try to call loadData() it will show it then. 如果我尝试调用loadData(),它将显示它。

How can i avoid component rendering before loading finishes? 如何避免在加载完成之前渲染组件?

Actions : 动作:

 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 } }; 

Reducer : 减速机:

 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; } } 

Component itself : 组件本身:

 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 : 更新@stinodes: 在此处输入图片说明

This fixes the issue but i think its not the proper way to do it : 这解决了问题,但我认为这不是正确的解决方法:

 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 }); } 

You can use the componentWillMount -hook instead of the componentDidMount . 您可以使用componentWillMount -hook代替componentDidMount
Using the first, sets it before the render. 使用第一个,在渲染之前设置它。 The latter fires after the component is rendered for the first time. 后者在首次渲染组件后触发。


edit : Since you're using redux to update your global state and then get your data passed into your props, you will want to fetch your courses when your component mounts. 编辑 :由于您正在使用redux更新全局状态,然后将数据传递到props中,因此您将希望在安装组件时获取您的课程。 You have this in place, by loading your data in the componentDidMount -hook. 您可以通过将数据加载到componentDidMount -hook中来实现此目的。
However, you won't need the async keyword, since redux will be passing the courses through your component's props anyway. 但是,您不需要async关键字,因为无论如何,redux都会通过组件的props传递课程。

When your component's props are updated, it will do a rerender as well. 组件的道具更新后,它也会重新渲染。 If you want to have your dataSource in your state, you can use the componentWillReceiveProps -hook. 如果要使您的dataSource处于状态,则可以使用componentWillReceiveProps -hook。 This hook will be fired when your component receives new properties. 当您的组件收到新属性时,将触发此挂钩。
When this is called, you can add your populated datasource to your state. 调用此方法时,可以将填充的数据源添加到您的状态。 This won't cause a new render. 不会导致新的渲染。

Example: 例:

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
        })

    }

    /* ... */
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM