0

I have a list of zones, I want to display. Now I've created a simple test. On a button a click a dummy entry should be added to the list. The variable is being updated, but the list component does not show the new entry.

Here is my code:

import React, { Component } from 'react';
import FreightList from './FreightList';
import ZoneList from './ZoneList';

class FreightCapture extends Component {

    constructor(props) {
        super(props);
        this.state = {
            freights: props.freights,
            zones: [{ID:"1",Fracht_ID:"2",Gebiet_von:"test"}],
            freightListId: 1,
            zoneListId: 2
        };
    }

    testOnClick(event) {
        event.preventDefault();
        let newEntry = [{ID:"2",Fracht_ID:"2",Gebiet_von:"test test"}];
        this.setState({
            zones: this.state.zones.concat(newEntry)
        })
    }

    render() {
        return (
            <div>
                <FreightList freights={this.state.freights} parent={this} key={this.state.freightListId} />

                <ZoneList zones={this.state.zones} key={this.state.zoneListId} />
                <button onClick={this.testOnClick.bind(this)}>Test</button>
            </div>
        );
    }
}

export default FreightCapture

ZoneList.js:

import React, { Component } from 'react';
import Zone from './Zone';

class ZoneList extends Component {

    constructor(props) {
        super(props);
        this.state = {
            zones: props.zones
        };
    }

    handleFreightClick(event) {

    }

    render() {
        return (
            <div className="panel panel-default">
                <div className="panel-heading">
                    Zones
                </div>
                <div className="panel-body">
                    <div className="table-responsive">
                        <table className="table table-hover table-striped">
                            <thead>
                                <tr>
                                    <th className="padding5px">ID</th>
                                    <th className="padding5px">Fracht_ID</th>
                                    <th className="padding5px">Land_Nr</th>
                                    <th className="padding5px">Gebiet_von</th>
                                    <th className="padding5px">Gebiet_bis</th>
                                    <th className="padding5px">Suchart_Nr</th>
                                    <th className="padding5px">Zone_Nr</th>
                                    <th className="padding5px">Zonen</th>
                                </tr>
                            </thead>
                            <tbody>
                            {
                                this.state.zones.map((zone)=> {
                                  return (
                                    <Zone zone={zone} key={zone.id} />
                                  );
                                })
                            }
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        );
    }
}

export default ZoneList

Zone.js:

import React, { Component } from 'react';

class Zone extends Component {

    constructor(props) {
        super(props);
        this.state = {
            zone: props.zone
        };
    }

    render() {
        return (

                <tr className="cursorPointer">
                    <td>
                        <div className="checkbox">
                          <label>
                            <input type="checkbox" value="" />
                          </label>
                        </div>
                    </td>
                    <td>
                        { this.state.zone.ID }
                    </td>
                    <td>
                        { this.state.zone.Fracht_ID }
                    </td>
                    <td>
                        { this.state.zone.Gebiet_von }
                    </td>
                    <td>
                        { this.state.zone.Gebiet_bis }
                    </td>
                    <td>
                        { this.state.zone.Land_Nr }
                    </td>
                    <td>
                        { this.state.zone.Suchart_Nr }
                    </td>
                    <td>
                        { this.state.zone.Zone_Nr }
                    </td>
                    <td>
                        { this.state.zone.Zonen }
                    </td>
                </tr>

        );
    }
}

export default Zone

When I click on the button, I can see the variable is being updated, but the component, which displays the list is not showing the new entry. Why? enter image description here

dns_nx
  • 3,651
  • 4
  • 37
  • 66

1 Answers1

3

When a child component uses a local state you should update that state on each new prop received. you can do that with componentWillReceiveProps

A followup to your comment:
Yes, each component that "maps" the props it receives to its local state should set its state on each new props received.
I think i can see where you got confused, you mapped the props to the state in the constructor call, but don't forget, the constructor invoked only ONCE.
The render will get invoked on each state change, but you are not changing the state, hence it won't re:render it self.
The way to change the state when new props received is with componentWillReceiveProps.
With that said, i really recommend to use a stateless components that has no state nor life cycle methods where ever possible.
I recommend reading this post by Cory House about the benefits of stateless components

Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99