admin管理员组

文章数量:1287489

I am in need of help, I am coding this form and after I submit it, the state for "posted" changes from false to true and I would expect "return Redirect to="/landing" ;" to redirect me to the landing page, however, it doesn't which I assume is because the line doesn't re-run after the initial render. I was hoping that changing the state of "posted" would cause a re-render. I have heard about using history push and tried to adapt it to my code yet I failed. I don't know how to wrap my ponent with "withRouter" given that I have it already wrapped with "connect". How can I achieve this? I have read numerous posts about this yet I can't figure how to adapt it to my code. Any help is appreciated.

import React, { useState } from "react";
import Navbar from "./Navbar";
import { connect, useDispatch } from "react-redux";
import { Redirect } from "react-router-dom";
import { createProject } from "../actions/projectAction";
import PropTypes from "prop-types";
import { push } from "connected-react-router";

const EditProject = ({ posted, createProject }) => {
  const dispatch = useDispatch();
  const [formData, setFormData] = useState({
    projectTitle: "",
    projectDescription: "",
    deliveryDate: ""
  });

  const { projectTitle, projectDescription, deliveryDate } = formData;

  const onChange = e => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const onSubmit = async e => {
    e.preventDefault();
    createProject({ projectTitle, projectDescription, deliveryDate });
    dispatch(push("/login"));
  };

  if (posted) {
    return <Redirect to="/landing" />;
  }

  return (
    <div>
      <Navbar />
      <div className="container">
        <form onSubmit={e => onSubmit(e)}>
          <h4>Project Title</h4>
          <input
            name="projectTitle"
            value={projectTitle}
            className="form-control"
            placeholder="Your project title"
            onChange={e => onChange(e)}
          />
          <h4>Delivery Date</h4>
          <input
            type="date"
            className="form-control"
            name="deliveryDate"
            value={deliveryDate}
            onChange={e => onChange(e)}
          />
          <h4>Description</h4>
          <textarea
            name="projectDescription"
            value={projectDescription}
            className="form-control"
            rows="10"
            onChange={e => onChange(e)}
          ></textarea>
          <input type="submit" className="btn btn-primary" value="Create" />
          <a href="/projects" className="btn btn-danger">
            Cancel
          </a>
        </form>
      </div>
    </div>
  );
};

EditProject.propTypes = {
  createProject: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  posted: state.posted
});

export default connect(mapStateToProps, { createProject })(EditProject);

I am in need of help, I am coding this form and after I submit it, the state for "posted" changes from false to true and I would expect "return Redirect to="/landing" ;" to redirect me to the landing page, however, it doesn't which I assume is because the line doesn't re-run after the initial render. I was hoping that changing the state of "posted" would cause a re-render. I have heard about using history push and tried to adapt it to my code yet I failed. I don't know how to wrap my ponent with "withRouter" given that I have it already wrapped with "connect". How can I achieve this? I have read numerous posts about this yet I can't figure how to adapt it to my code. Any help is appreciated.

import React, { useState } from "react";
import Navbar from "./Navbar";
import { connect, useDispatch } from "react-redux";
import { Redirect } from "react-router-dom";
import { createProject } from "../actions/projectAction";
import PropTypes from "prop-types";
import { push } from "connected-react-router";

const EditProject = ({ posted, createProject }) => {
  const dispatch = useDispatch();
  const [formData, setFormData] = useState({
    projectTitle: "",
    projectDescription: "",
    deliveryDate: ""
  });

  const { projectTitle, projectDescription, deliveryDate } = formData;

  const onChange = e => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const onSubmit = async e => {
    e.preventDefault();
    createProject({ projectTitle, projectDescription, deliveryDate });
    dispatch(push("/login"));
  };

  if (posted) {
    return <Redirect to="/landing" />;
  }

  return (
    <div>
      <Navbar />
      <div className="container">
        <form onSubmit={e => onSubmit(e)}>
          <h4>Project Title</h4>
          <input
            name="projectTitle"
            value={projectTitle}
            className="form-control"
            placeholder="Your project title"
            onChange={e => onChange(e)}
          />
          <h4>Delivery Date</h4>
          <input
            type="date"
            className="form-control"
            name="deliveryDate"
            value={deliveryDate}
            onChange={e => onChange(e)}
          />
          <h4>Description</h4>
          <textarea
            name="projectDescription"
            value={projectDescription}
            className="form-control"
            rows="10"
            onChange={e => onChange(e)}
          ></textarea>
          <input type="submit" className="btn btn-primary" value="Create" />
          <a href="/projects" className="btn btn-danger">
            Cancel
          </a>
        </form>
      </div>
    </div>
  );
};

EditProject.propTypes = {
  createProject: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
  posted: state.posted
});

export default connect(mapStateToProps, { createProject })(EditProject);
Share Improve this question asked Nov 30, 2019 at 4:52 K. GreenK. Green 1031 gold badge1 silver badge4 bronze badges 1
  • This code should work. Did you check that the value of posted is as expected? (e.g. console.log('posted', posted) just above the if) If it's true, the problem would be in the way how router is initialized (e.g. a typo in <Route path="/lnding">). If not, the problem is most likely in redux (e.g. the reducer not setting state.posted correctly). – Aprillion Commented Nov 30, 2019 at 13:57
Add a ment  | 

3 Answers 3

Reset to default 4

I think you have to define your route. From my following code you can get a little bit idea of the routing.

In App.js basically I defined the routes and I have created two more functional ponents Landing and EditProject to simulate your idea. Moreover I have used Link for navigation purpose

App.js

import React, { Component } from "react";
import { BrowserRouter, Route, Switch, Link } from "react-router-dom";
import EditProject from "./editProject";
import Landing from "./landing";

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <div id="container">
          <div>
            <Link to="/">Landing Page</Link>
            <Link to="/editproject">Edit Project</Link>
          </div>
          <Switch>
            <Route path="/editproject" ponent={EditProject} />
            <Route exact path="/" ponent={Landing} />
          </Switch>
        </div>
      </BrowserRouter>
    );
  }
}

export default App;

Landing functional ponent

import React from "react";

const Landing = () => {
  return <h1>Landing Page</h1>;
};

export default Landing;

EditProject functional ponent

import React from "react";

const EditProject = props => {
  function handleSubmit(e) {
    e.preventDefault();
    console.log("submitted");
    //do your task here before redirect
    //...
    props.history.push("/");
  }

  return (
    <div>
      <h1>Edit Project</h1>
      <form onSubmit={handleSubmit}>
        <button>Submit</button>
      </form>
    </div>
  );
};

export default EditProject;

Hope it will help you.

There're two things I would like to address in your code.

if EditProject ponent is going straight to Route then you have access to push.

const EditProject = ({ { posted, createProject, history: { push } }) => {
    push() // your access to push
}

secondly, In your connect, I don't support that idea of your connect. Probably, the submit function wasn't running.

You can do something like below to make a difference.

export default connect(mapStateToProps, { handleNewProject, createProject })(EditProject);

Now, to Re-write EditProject ponent would be

import React, { useState, useEffect } from "react";

const EditProject = ({ { posted, handleNewProject, history: { push } }) => {
    push() // your access to push
    // useEffect React ponent life cycle Hook
    useEffect(() => () => push('/landing'), [posted]);

}

Notice I use React Hook just like the way you would use React class ponent life circle.

Say, on Logout submit button, I want to goto user/login page:

export default function MyComponent(props) {    
    // ...

    const handleSubmit = async (event) => {
        props.history.push('/user/login');
    }
}

NOTE: if props is not present in the ponent argument, you can add it.


Some other non-standard ways in react.js (but monly used in large projects)

One of the below will work:

let url = '/user/login'

props.history.push(url);

window.location = url;
window.location.href = url;
window.location.replace(url);

window.open(url)
window.open(url, "_self")
window.open(url, '_blank');
window.open(url, 'newWindow');
window.open(url, 'newwin');

window.location.reload(true);

本文标签: javascriptRedirect with React Functional ComponentsStack Overflow