React, Redux - redirect after object is created (using new object id in URL)

末鹿安然 提交于 2020-05-17 07:15:20

问题


I think I have a quite common problem, but can't find up to date answer that I would be sure is good practice.

I'm writing a forum app using React, Redux, React Router DOM. I'm using BrowserRouter.

Here is what I want to do: after I post a request to create a thread and it is fulfilled, I want to redirect user to newly created thread page (I need object id that I will get in response for URL).

component

class CreateThread extends React.Component {

  handleCreateThread = (values) => {
    this.props.createThread(values);

  [...more code...]
}

actions

export const createThread = (data) => async dispatch => {
  try {
    const response = await instance().post('/api/threads/', data);
    // const { id, category } = response.data;
    // history.push(`/categories/${category.id}/threads/${id}`);
    dispatch({ type: types.CREATE_THREAD_FULFILLED, payload: response.data })
  } catch(err) {
    dispatch({ type: types.CREATE_THREAD_ERRORS, payload: err.response.data })
  }
};

What is the best way to do it? I think it would be easiest to redirect inside actions. Is it good practice? How can I access history object in this case? (The commented part in the code in actions does not work, I can't access history object like that). I was searching for an answer but I found many that are not up-to-date or contradictory and I'm very confused.

------------EDIT----------

So I have followed an advice of Ahmad Nawaz Khan, but when trying to access history.push inside action creator I'm getting an error TypeError: "_routing__WEBPACK_IMPORTED_MODULE_3__.default.push is not a function"

// routing/history.js
import { createBrowserHistory } from 'history';
export default createBrowserHistory();

// routing/index.js
import { Router } from 'react-router-dom';
import history from './history';

const Routing = (props) => {
  return (
    <Router history={history}>
      ...

// redux/actions/index.js
import history from '../../routing';

export const createThread = (data) => async dispatch => {
  try {
    const response = await instance().post('/api/threads/', data);    
    const { id, category } = response.data;
    history.push(`/categories/${category.id}/threads/${id}`);
    dispatch({ type: types.CREATE_THREAD_FULFILLED, payload: response.data })
  } catch(err) {
    ...

"history": "^4.10.1", "react-router-dom": "^5.1.2", "react": "^16.12.0"


回答1:


If you have created a custom history object then you cannot use BrowserRouter, you have to use Router instead, which works similar to the BrowerRouter except that it takes custom a history object.

create a history object (if not created)

//history.js
import { createBrowserHistory } from "history";
export default createBrowserHistory();

Change BrowerRouter to Router

import Router from "react-router-dom";

Import and pass the history object to the Router (history.push wouldn't work if you haven't passed the history object to the router.)

import history from "./history.js"
...
<Router history={history}>

Now you can either redirect a user from the action creator or CreateThread component. And yes it's a good practice to redirect a user from action creator but if you want to do that from CreateThread component then you would have to return a promise from the createThread action creator.




回答2:


History.js

import createHistory from 'history/createHashHistory';
export default createHistory()

Action.js

import history from './history'
history.push('/send to my new page');



回答3:


Looking at your imports and your file usages I see that the problem here is just of an incorrect import.

You have defined history to be in history.js file however you try to import it from routing/index.js like

Update your import of history and it should work for you

// redux/actions/index.js
import history from '../../routing/history.js';

export const createThread = (data) => async dispatch => {
  try {
    const response = await instance().post('/api/threads/', data);    
    const { id, category } = response.data;
    history.push(`/categories/${category.id}/threads/${id}`);
    dispatch({ type: types.CREATE_THREAD_FULFILLED, payload: response.data })
  } catch(err) {
    ...


来源:https://stackoverflow.com/questions/61686352/react-redux-redirect-after-object-is-created-using-new-object-id-in-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!