问题
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