Reputation: 1923
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
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
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