The state is updated , also its giving the latest data to props with mapStateToProps , however, its not rendering the child component StudentList and Student in Map method , once the props is updated.
Once you add student , you can see the updated state, which is sent to the Form component.
Here is my code,
Index.js
var store = createStore(studentFormReducer);
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
App.js
import React, { Component } from 'react';
import './App.css';
import StudentFormContainer from './containers/StudentFormContainer';
import StudentList from './components/StudentList'
class App extends Component {
render() {
return (
<div className="container-fluid">
<StudentFormContainer></StudentFormContainer>
<StudentList></StudentList>
</div>
);
}
}
export default App;
StudentForm : Component
import React, { Component } from 'react';
export default class StudentForm extends Component {
constructor(){
super();
this.state={
student : {
name:"",
}
};
}
render() {
return (
<div className="formcontainer">
<button type="button" name="addstudent" id="addstudent" onClick={(e)=>{this.props.addStudent(this.state.student); console.log(this.props.currentstate)}} className="btn btn-primary btn-lg ">Add student</button>
<form>
<div className="form-group">
<label htmlFor="name">Student name</label>
<input type="text" name="name" id="name" value={this.state.student.name} onChange={(e)=>{e.preventDefault(); this.setState({student:{name : e.target.value}})}} className="form-control" placeholder="Enter student name" aria-describedby="helpId"/>
</div>
</form>
</div>
);
}
}
StudentFormContainer : Container
import {connect} from 'react-redux';
import StudentForm from '../components/StudentForm'
import {addStudentAction} from '../actions/index'
const mapStateToProps = (state)=>{
console.log("New state updated");
return{
studentlist : state.studentlist,
currentstate : state
};
}
const mapDispatchToProps = (dispatch)=>{
return{
addStudent : (student)=>{console.log("Dispatching");dispatch(addStudentAction(student))}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(StudentForm)
StudentList : Component + Container
import React, { Component } from 'react';
import {connect} from 'react-redux';
import Student from './Student'
class StudentList extends Component {
render() {
return (
<div className="studentlist">
{this.props.studentlist.map(
(student,index)=>(<Student key={index} student={student}></Student>))
}
</div>
);
}
}
const mapStateToProps = (state)=>{
return{
studentlist : state.studentlist,
currentstate : state
};
}
export default connect(mapStateToProps)(StudentList)
Student Form Reducer
export const studentFormReducer = (state={},action)=>{
if(action.type=="ADD_STUDENT"){
var id = state.studentlist.length+1;
action.student.id = id;
state.studentlist.push(action.student);
return state;
}
else{
if(state.studentlist===undefined){
var newstate2 = {studentlist:[]}
return newstate2;
}else{
return state;
}
}
}
Action
export const addStudentAction = (student)=>
{
return{
type : "ADD_STUDENT",
student : student
}
};
state
should be immutable. In your code you manipulated directly the state
object.
state.studentlist.push(action.student);
Using object spread operator , you will be able to fix this:
switch(action.type) {
case "ADD_STUDENT":
let student = action.student;
student.id = state.studentList.length + 1; // set student id
return {
...state,
studentList: [
...state.studentList,
student // add new student to student list
]
};
default:
return state;
}
i think you are trying to add new student and update that student object into existing array if i am not wrong. it's not the good choise to use if-condition in reducer function better use switch case.
const initialState = { studentlist: [] } export const studentFormReducer = (state=initialState, action)=>{ switch(action.type){ case "ADD_STUDENT": return{ ...state, studentlist: [...state.studentlist, action.student] } default: return state; } }
Try this in reducer
case ADD_STUDENT :
return {
...state,
studentList: state.studentList.concat(action.student)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.