在React组件渲染之前重定向到新的前端路由

时间:2018-09-17 15:15:34

标签: javascript reactjs routing frontend react-router-dom

我希望为我的任务管理应用程序添加功能,该功能允许用户单击“添加任务”按钮,这将创建一个空白任务,更新任务列表,然后重新路由至该任务的编辑路由“ app /任务/:id”。这将允许任务列表“ app / tasks”和任务的编辑页面“ app / tasks /:id”同时显示在“ app / tasks /:id”上。我目前的方法是让我的createTask({})方法分派createTask(task)操作和mountTask(taskId)操作。 mountTask(taskId)会将最近创建的任务的ID设置为我的任务列表状态切片,以用于重定向。我想在TaskPage(用于TaskList和TaskForm的容器)中执行的操作是,在呈现之前检查是否有处于状态的MountedTaskId,然后相应地重新路由。我最初决定使用componentWillReceiveProps,但是,在阅读了React文档之后,我发现这称为AFTER渲染。由于我的路线是在TaskPage中呈现的,因此重定向不会对路线产生任何影响,因为它已经在重定向之前进行了呈现。调用渲染之前处理此重定向的最佳方法是什么?

前端路由

TaskPage - "api/tasks"
TaskForm - "api/tasks/:id"

TaskPage

class TaskPage extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    this.fetchAllTasks();
  }

  componentWillReceiveProps(newProps) {
    if (newProps.mountedTaskId && this.props.mountedTaskId !== newProps.mountedTaskId) {
      this.props.history.push(RouteConstants.TASKS + `${newProps.mountedTaskId}`);
    }
  }

  render() {
    return (
      <div>
        <TaskList
          tasks={ this.props.tasks }
          createTask={ this.props.createTask }
          mountTask={ this.props.mountTask } />
        <Route
          path={ RouteConstants.TASKS_FORM }
          component={ TaskForm } />
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    tasks: Object.values(state.entities.tasks),
    mountedTaskId: state.ui.taskList.mountedTaskId
  };
}

function mapDispatchToProps(dispatch) {
  return {
    fetchAllTasks: () => {
      return dispatch(fetchAllTasks());
    },
    createTask: (task) => {
      return dispatch(createTask(task));
    },
    mountTask: (task) => {
      return dispatch(mountTask(task));
    },
    unmountTask: () => {
      return dispatch(unmountTask());
    }
  };
}

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(TaskPage));

TaskList

export default class TaskList extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(type) {
    //Depending on type, create a blank task or section,
    //add it to the list, and redirect to that task/section's
    //edit route.

    return () => {
      switch (type) {
        case "task":
          this.props.createTask({});
          break;
        case "section":
        //Ignore for now...
          break;
        default:
          return null;
      }
    };
  }

  render() {
    const tasks = this.props.tasks.map( (task) => {
      return (
        <TaskItem task={ task } />
      );
    });

    return (
      <div>
        <div className="task-list-header">
          <button onClick={ this.handleClick("task") }>Add Task</button>
          <button onClick={ this.handleClick("section") }>Add Section</button>
        </div>
        <div className="task-list-container">
          <ul className="task-list">
            { tasks }
          </ul>
        </div>
      </div>
    );
  }
}

TaskForm

export default class TaskForm extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <p>Task Form</p>
      </div>
    );
  }
}

0 个答案:

没有答案