Shruthi R
Shruthi R

Reputation: 1923

ReactJS - How to redirect another page using history.push by passing data?

In react app, I am using below packages

"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.1.3",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.1"

Also using reducer like

export function reducer(state = initialState, action) {
  if(action.type === 'GET_FRIENDS'){
    return {...state};
  } else if (action.type === 'ADD_FRIEND'){
    return {state, friends: state.friends.concat(action.friend) };
  } else if (action.type === 'DELETE_FRIEND'){
    return {...state, friends: state.friends.filter(item => item.id !== parseInt(action.friendId))};
  }
  return state;
}

In main index.js,

import React, { useReducer } from 'react';
import List from './List';
import FormInput from './FormInput';
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom';
import {reducer, initialState } from './reducer';

function Friends(){
   const [state, dispatch] = useReducer(reducer, initialState);

   function handleDelete(id){
     dispatch({type: 'DELETE_FRIEND', friendId: id});
   }

   return(
     <Router>
       <nav className="navbar navbar-light">
         <ul className="nav navbar-nav">
            <li><Link to="/">Home</Link></li>
            <li><Link to="/list">List</Link></li>
            <li><Link to="/create">Add</Link></li>
         </ul>
        </nav>
        <Switch>
           <Route exact path="/"><Home /></Route>
           <Route path="/list"><List friends={state.friends} handleDelete={(id) => handleDelete(id)} /></Route>
           <Route path="/create"><FormInput /></Route>
        </Switch>
      </Router>
    );
 }
 export default Friends;

And child component FormInput is like,

import React, { useReducer, useState } from 'react';
import { useHistory } from "react-router-dom";
import {reducer, initialState } from '../reducer';

function FormInput(){
  const [state, dispatch] = useReducer(reducer, initialState);
  const initFriend = {id: null, name: '', phone: '', email: '', work: '', city: ''};
  const [friend, setFriend] = useState(initFriend);
  let history = useHistory();

  function handleOnChange(e){
    const { name, value } = e.target;
    setFriend({...friend, [name]: value});
  }

  function handleOnSubmit(e){
    friend.id = (state.friends.length - 1) + 1;
    dispatch({type: 'ADD_FRIEND', friend: friend});
    e.preventDefault();
    history.push("/list");
  }

  return(
     <form onSubmit={(e) => handleOnSubmit(e)} autoComplete="off">
        <div className="form-group row">
           <label className="col-sm-2 col-form-label">Name</label>
           <div className="col-sm-10">
              <input type="text" name="name" className="form-control form-control-lg" defaultValue={''} onChange={(e) => handleOnChange(e)} />
           </div>
        </div>
        <div className="form-group row">
           <label className="col-sm-2 col-form-label">Phone</label>
           <div className="col-sm-10">
              <input type="text" name="phone" className="form-control form-control-lg" defaultValue={''} onChange={(e) => handleOnChange(e)} />
           </div>
        </div>
     </div>
     <button type="submit" className="btn btn-primary btn-lg">Save</button>
    </form>
  );
}
export default FormInput;

Right now after form submission page is redirecting without updated data.

Actually I want to add a new friend data to state.friends after form submission. And also it should redirect to /list page by displaying newly added row.

Also please let me know the answer in detail because I am new to ReactJS.

Upvotes: 0

Views: 1846

Answers (2)

Zahir Masoodi
Zahir Masoodi

Reputation: 858

You can pass state using history also.

    props.history.push({
    path:"/list",
    state:someData
})

In the list component
props.location.state ```

Upvotes: 0

Julius Guevarra
Julius Guevarra

Reputation: 888

You are using the same reducer which you used both in Friends component and FormInput component.

Whenever you submit the form and added data to the state in FormInput, the data you've just added will only be saved in FormInput and not in Friends component and the state will be deleted because the FormInput will be unmounted upon changing route.

To solve this, you need to use the reducer only in the parent/main which happened to be Friends component in your case and delete the useReducer hook in FormInput.

App.js

import React, { useReducer } from 'react';
import List from './List';
import FormInput from './FormInput';
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom';
import {reducer, initialState } from './reducer';

function Friends(){
   const [state, dispatch] = useReducer(reducer, initialState);

   function handleDelete(id){
     dispatch({type: 'DELETE_FRIEND', friendId: id});
   }

   return(
     <Router>
       <nav className="navbar navbar-light">
         <ul className="nav navbar-nav">
            <li><Link to="/">Home</Link></li>
            <li><Link to="/list">List</Link></li>
            <li><Link to="/create">Add</Link></li>
         </ul>
        </nav>
        <Switch>
           <Route exact path="/"><Home /></Route>
           <Route path="/list"><List friends={state.friends} handleDelete={(id) => handleDelete(id)} /></Route>
           <Route path="/create">
               <FormInput state={state} dispatch={dispatch}/> //PASS THE STATE & DISPATCH 
           </Route>
        </Switch>
      </Router>
    );
 }
 export default Friends;

Now you only need to use the passed dispatch and state prop in FormInput

function FormInput({ state, dispatch }){
  const initFriend = {id: null, name: '', phone: '', email: '', work: '', city: ''};
  const [friend, setFriend] = useState(initFriend);
  let history = useHistory();
 
  // ...
}

This though is not a good practice. That's why use Context in this case. See the codesandbox demo for the context version.

For details about React Context

Upvotes: 0

Related Questions