【问题标题】:How can i redirect after successful submit of form using react-redux使用 react-redux 成功提交表单后如何重定向
【发布时间】:2021-02-14 03:51:55
【问题描述】:

action.js

import axios from 'axios';
import { EVENT_ADD_FAIL, EVENT_ADD_REQUEST, EVENT_ADD_SUCCESS } from '../constraints/eventConstraint';

const addEvent = (event) => async (dispatch) => {
 dispatch({ type: EVENT_ADD_REQUEST, payload: event });
 try {
    const { data } = await axios.post(`http://localhost:4000/event`, event);
    dispatch({ type: EVENT_ADD_SUCCESS, payload:data });
 }
 catch (error) {
    dispatch({ type: EVENT_ADD_FAIL, payload:error.message });
 };
};


export { addEvent };

约束.js

export const EVENT_ADD_REQUEST = 'EVENT_ADD_REQUEST';
export const EVENT_ADD_SUCCESS = 'EVENT_ADD_SUCCESS';
export const EVENT_ADD_FAIL = 'EVENT_ADD_FAIL';

reducer.js

import {EVENT_ADD_FAIL, EVENT_ADD_REQUEST, EVENT_ADD_SUCCESS } from "../constraints/eventConstraint";

function eventAddReducer(state = {}, action) {
 switch(action.type) {
    case EVENT_ADD_REQUEST:
        return { loading: true };
    case EVENT_ADD_SUCCESS:
        return { loading: false, event: action.payload, success:true };
    case EVENT_ADD_FAIL:
        return { loading: false, error: action.payload, success:false };
    default:
        return state
 };
};

export { eventAddReducer }

store.js

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { eventAddReducer } from './reducers/eventReducer';

const initialState = {};
const reducer = combineReducers({
  addEvent: eventAddReducer
});

const store = createStore(reducer, initialState, compose(applyMiddleware(thunk)));
export default store

event.js

import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useHistory } from 'react-router-dom';
import { addEvent } from '../actions/eventAction';

const AddEvent = () => {
 const history = useHistory();
 const [event, setEvent] = useState();
 const addNewEvent = useSelector(state => state.addEvent);
 console.log(addNewEvent)
 const dispatch = useDispatch();

 const handleChange = e => {
    setEvent({ ...event,[e.target.name]:e.target.value})
 };

 const submitHandler = async (e) => {
    e.preventDefault();
    await dispatch(addEvent(event));
 };

// if(addNewEvent.success === true) {   
//     history.push('/')
// };   ===========>>>>>>>>>>> It works at first but after submission first time next time it automatically redirects to '/' because react-redux holds state

return (
    <>
        <form onSubmit = { submitHandler } >
            <div className="form-group">
                <label htmlFor="name">Name:</label>
                <input type="text" className="form-control" id="name" name="name" onChange={e => handleChange(e)} />
            </div>
            <div className="form-group">
                <label htmlFor="description">Description:</label>
                <input type="text" className="form-control" id="description" name="description" onChange={e => handleChange(e)} />
            </div>
            <div className="form-group">
                <label htmlFor="price">Price:</label>
                <input type="text" className="form-control" id="price" name="price" onChange={e => handleChange(e)} />
            </div>
            <Link to='/'> <button type="button" className="btn btn-success"> Back </button> </Link>
            <button type="submit" className="btn btn-success float-right"> Add Event </button>
        </form>
    </>
 )
};

export default AddEvent

一切正常,但我希望在成功提交表单后它需要重定向到某个页面。没有 react-redux 很简单,我们可以在提交表单后简单地重定向,但我正在尝试学习 redux 并且对 redux 不太了解。我尝试在reducer中使用success = true,它第一次工作,但是当我尝试打开链接时redux保持状态,它自动重定向到主页,因为success = true被react-redux保持。任何帮助将不胜感激

【问题讨论】:

  • 你可以使用一个中间件在调度的动作对象中寻找一个特定的键,并在找到它时触发一个路由重定向。
  • 能否详细说明一下

标签: javascript reactjs redux react-redux redux-thunk


【解决方案1】:

首先:确保每次操作都重置success

function eventAddReducer(state = {}, action) {
  switch(action.type) {
     case EVENT_ADD_REQUEST:
         return { 
           loading: true,
           success: null // <-- Look at this
          };
    /** ... */
  };
};

第二:success store-variable 连接到您的组件,并在componentDidupdate 事件中检查它,例如:

import { connect } from 'react-redux';

class AddEvent extends React.Component {
  componentDidUpdate(prevProps) {
    const {success} = this.props;
    const {succcess: prevSuccess} = prevProps;

    if (success && success !== prevSuccess) {
      /** Redirect here */
    }
  }
  /** .... */
}

const mapStateToProps = ({ addEvent: { success } }) => ({
  success
});

export default connect(mapStateToProps)(AddEvent);

使用钩子

const AddEvent = ({ success }) => {
  useEffect(() => {
    if (success) {
      /** Redirect here */
    }
  }, [success]); // <-- This will make sure that the effect only runs when success variable has changed
};

const mapStateToProps = ({ addEvent: { success } }) => ({
  success
});

export default connect(mapStateToProps)(AddEvent);

【讨论】:

  • 但我想使用功能组件而不是类组件
  • 它仍然无法正常工作,因为在成功为真后它不会命中,直到我们提交表单
【解决方案2】:

我知道这不是最理想的解决方案,但是如何创建一个重置成功的操作并将其分派到 useEffect 中呢?

类似这样的:

减速器

import {EVENT_ADD_FAIL, EVENT_ADD_REQUEST, EVENT_ADD_SUCCESS } from "../constraints/eventConstraint";

function eventAddReducer(state = {}, action) {
 switch(action.type) {
    case EVENT_ADD_REQUEST:
        return { loading: true };
    case EVENT_ADD_SUCCESS:
        return { loading: false, event: action.payload, success:true };
    case EVENT_ADD_FAIL:
        return { loading: false, error: action.payload, success:false };
case RESET:
      return {
         ...state, 
         loading: false, 
         success:false
      } // This will reset everything including success
    default:
        return state
 };
};

export { eventAddReducer }

并在您的 event.js 文件中调用将调度 RESET 的操作。确保将其放在 useEffect 中。


import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link, useHistory } from 'react-router-dom';
import { addEvent } from '../actions/eventAction';

const AddEvent = () => {
 const history = useHistory();
 const [event, setEvent] = useState();
 const addNewEvent = useSelector(state => state.addEvent);
 console.log(addNewEvent)
 const dispatch = useDispatch();
React.useEffect(() =>{
myResetAction()

}, [])
 const handleChange = e => {
    setEvent({ ...event,[e.target.name]:e.target.value})
 };

const submitHandler = async (e) => {
    e.preventDefault();
    await dispatch(addEvent(event));
 };

// if(addNewEvent.success === true) {   
//     history.push('/')
// };   ===========>>>>>>>>>>> It works at first but after submission first time next time it automatically redirects to '/' because react-redux holds state

return (
    <>
        <form onSubmit = { submitHandler } >
            <div className="form-group">
                <label htmlFor="name">Name:</label>
                <input type="text" className="form-control" id="name" name="name" onChange={e => handleChange(e)} />
            </div>
            <div className="form-group">
                <label htmlFor="description">Description:</label>
                <input type="text" className="form-control" id="description" name="description" onChange={e => handleChange(e)} />
            </div>
            <div className="form-group">
                <label htmlFor="price">Price:</label>
                <input type="text" className="form-control" id="price" name="price" onChange={e => handleChange(e)} />
            </div>
            <Link to='/'> <button type="button" className="btn btn-success"> Back </button> </Link>
            <button type="submit" className="btn btn-success float-right"> Add Event </button>
        </form>
    </>
 )
)}

这样做会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-13
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多