我正在开发一个几乎完全按照以下路线运行的应用:/task/:taskId
并且在/
路线上无需呈现任何内容。相反,当您启动应用程序时,它应该重定向到任务。就像你打开懒散而且你在一个频道时一样。不在某些页面上说请选择一个频道。我无法弄清楚我想从数据库加载任务的位置。
现在,我有一个加载/
的组件,并且在componentDidMount
方法中,我从数据库加载任务。加载任务后,我会history.push
重定向到数据库中任务数组中的第一个任务。
这一切都很有效,直到我被重定向到特定任务然后刷新页面。也就是说,如果我在/task/foobar
并刷新页面,则应用程序不会加载任何内容,因为任务仅从/
的数据库加载。
那么无论我在哪个页面上,确保我的数据都被加载的正确方法是什么?
编辑 - 添加一些代码供参考:
/routes.js - /使用Master.js和/ task /:taskId使用TaskPage.js
import React from 'react';
import { Switch, Route } from 'react-router';
import App from './containers/App';
import Master from './containers/Master';
import TaskPage from './containers/TaskPage';
export default () => (
<App>
<Switch>
<Route exact path="/" component={Master} />
<Route path="/task/:taskId" component={TaskPage} />
</Switch>
</App>
);
/containers/Master.js - loadTasks是将任务数据传递给任务reducer的动作创建者。还返回从本地nedb数据库加载后解析为任务数据的promise。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { loadTasks } from '../actions/tasks';
class Master extends Component {
componentDidMount() {
this.fetchData();
}
fetchData() {
this.props.loadTasks()
.then(tasks => {
const id = tasks[Object.keys(tasks)[0]]._id;
this.props.history.push(`/task/${id}`);
return true;
})
.catch(e => {
console.log('ERROR', e);
});
}
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
const mapStateToProps = (props, ownProps) => ({
taskId: ownProps.taskId
});
export default connect(mapStateToProps, {
loadTasks
})(Master);
/containers/TaskPage.js - 这里看不多。只需将道具传递给包裹的组件任务,只要应用程序加载/第一次就可以正常呈现。如果您直接点击/ task /:taskId,则无法加载任何内容,因为数据库中的任务数据仅在/
处加载到redux商店import { connect } from 'react-redux';
import Task from '../components/Task';
const mapStateToProps = ({ tasks }, { match: { params: { taskId } } }) => ({
tasks,
taskId
});
export default connect(mapStateToProps)(Task);
答案 0 :(得分:0)
编辑 - 我已经删除了我的旧答案,支持我认为基于我已经完成的一些挖掘的更好方法。
我在一些地方看到过Dan Abramov的一些事情让我觉得他在组件内部(不是容器)进行数据获取,他会使用componentDidMount生命周期方法来做所以。我唯一不确定的是如何最好地决定应用程序是否应显示加载状态。
在Dan和其他人中&#39;例子,他们只是检查state.loading是否为false并且state.items.length是否为0.这仅适用于您始终期望项目具有数据的情况。但在我的情况下,当你第一次启动应用程序时,你将没有数据,所以检查0长度并不是真的有用。相反,我已经向该州添加了一个initLoad属性。
如果有更好的方法,我可以采取其他方式处理这个问题。
<强> routes.js 强>
import React from 'react';
import { Switch, Route } from 'react-router';
import App from './containers/App';
import TaskPage from './containers/TaskPage';
export default () => (
<App>
<Switch>
<Route exact path="/" component={TaskPage} />
<Route path="/task/:taskId" component={TaskPage} />
</Switch>
</App>
);
<强> TaskPage.js 强>
import { connect } from 'react-redux';
import { withRouter } from 'react-router';
import { loadTasks } from '../actions/tasks';
import Task from '../components/Task';
const mapStateToProps = ({ tasks }, { match: { params: { taskId } } }) => ({
tasks,
taskId,
});
const mapDispatchToProps = dispatch => ({
loadTasks: () => dispatch(loadTasks())
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Task));
<强> Task.js 强>
import React, { Component } from 'react';
import type { tasksType } from '../reducers/tasks';
import SidebarContainer from '../containers/SidebarContainer';
class Task extends Component {
props: {
loadTasks: () => any,
initForm: () => any,
taskId: string,
tasks: tasksType,
history: any
};
componentDidMount() {
this.fetchData();
}
fetchData() {
this.props.loadTasks()
.then(tasks => {
const taskId = this.props.taskId;
if (!taskId) {
const id = tasks[Object.keys(tasks)[0]]._id;
this.props.history.push(`/task/${id}`);
}
return true;
})
.catch(e => {
console.log('ERROR', e);
});
}
render() {
const { tasks, taskId, initForm } = this.props;
if (!tasks.initLoad || (tasks.loading && Object.keys(tasks.items).length < 1)) {
return <div>Loading</div>;
}
return (
<div id="wrapper">
<SidebarContainer taskId={taskId} />
<div id="main">
<div id="group-details">
{tasks.initLoad && Object.keys(tasks.items).length > 0 ?
(<div>Task details would go here...</div>) :
(<div>Please create a task</div>)
}
</div>
</div>
</div>
);
}
}
export default Task;