简体   繁体   中英

State is updated, also its reflecting with props, in console.log, however the component is not re-rendering

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM