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>
);
}
}
这解决了问题,但我认为这不是正确的方法:
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
});
}
答案 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
})
}
/* ... */
}