JavaScript Why does my Component not update after posting data to REST service does component update when props change,react when does component

So I am trying to build my first react.js app and am wondering, why my page does neither update after POSTING a new player to my app via axios, nor after DELETING one. As I refresh the page afterwards the players are created or gone depending on the operation. So the API part is working just fine.

I have a PlayerPage.js like so:

PlayerPage.js

import React, { Component } from 'react';
import axios from 'axios';
import PlayerForm from './playerform';
import PlayCard from './playercard';

class PlayerPage extends Component {
  constructor(props) {
    super(props);
  }

  state = {
    players: []
  };

  componentDidMount() {
    axios
      .get('http://localhost:3001/player')
      .then(res => {
        const players = res.data;
        this.setState({ players });
      })
      .catch(console.log);
  }

  render() {
    return (
      <div>
        <h2>Add Player</h2>
        <PlayerForm />
        <hr></hr>
        <h2>Available Player</h2>
        {this.state.players.map(player => (
          <PlayCard player={player} key={player.id} />
        ))}
      </div>
    );
  }
}

export default PlayerPage;

It does reference (and fill in from API) the PlayerForm and PlayerCard component, which look like this:

playerform.js

import React, { Component } from 'react';
import axios from 'axios';
import {
  FormControl,
  FormGroup,
  FormLabel,
  Form,
  Button
} from 'react-bootstrap';

class PlayerForm extends Component {
  state = {
    name: '',
    nickname: ''
  };

  handleSubmit = e => {
    e.preventDefault();
    axios
      .post('http://localhost:3001/player', JSON.stringify(this.state), {
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json'
        }
      })
      .then()
      .catch(err => console.log(err));
  };

  handelChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  render() {
    return (
      <Form onSubmit={this.handleSubmit}>
        <FormGroup>
          <FormLabel>Name</FormLabel>
          <FormControl
            type="text"
            name="name"
            placeholder="Enter player name"
            onChange={this.handelChange.bind(this)}
          />
        </FormGroup>
        <FormGroup>
          <FormLabel>Nickname</FormLabel>
          <FormControl
            type="text"
            name="nickname"
            placeholder="Enter player nickname"
            onChange={this.handelChange.bind(this)}
          />
        </FormGroup>
        <Button variant="btn btn-primary" type="submit">
          Add
        </Button>
      </Form>
    );
  }
}

export default PlayerForm;

and playercard.js:

import React, { Component } from 'react';
import { Card, Button } from 'react-bootstrap';
import PropTypes from 'prop-types';
import axios from 'axios';

class PlayerCard extends Component {
  constructor(props) {
    super(props);
    this.player = props.player;

    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    axios
      .delete(`http://localhost:3001/player/${this.player.id}`)
      .then()
      .catch(console.log);
  }
  render() {
    return (
      <Card className="flex-row flex-wrap">
        <Card.Header>
          <Card.Img variant="left" src="https://via.placeholder.com/150" />
        </Card.Header>
        <Card.Body variant="center">
          <Card.Title>{this.player.name}</Card.Title>
          <Card.Subtitle>{this.player.nickname}</Card.Subtitle>
        </Card.Body>
        <Card.Body variant="right">
          <Button variant="btn btn-primary" onClick={this.handleClick}>
            Delete
          </Button>
        </Card.Body>
      </Card>
    );
  }
}

PlayerCard.propTypes = {
  player: PropTypes.object.isRequired
};

export default PlayerCard;

So the question is, why does my side not update properly? I am grateful for any hints. Thanks in advance.

Bonus question: How do I fetch the ip and port dynamically depending on where the node server is running?

Answer:1

Why it's not working:

Because you are not refreshing the list view when the form is submitted. React is not magic, you need to tell when you want the view to be rerender.

One way to to this is adding a onCreate prop to your playerform.js and run the function when the form is successfully submitted.

import React, { Component } from 'react';
import axios from 'axios';
import PlayerForm from './playerform';
import PlayCard from './playercard';

class PlayerPage extends Component {
  constructor(props) {
    super(props);
  }

  state = {
    players: []
  };

  loadPlayers() {
    axios
      .get('http://localhost:3001/player')
      .then(res => {
        const players = res.data;
        this.setState({ players });
      })
      .catch(console.log);
  }

  componentDidMount() {
    this.loadPlayers();
  }

  render() {
    return (
      <div>
        <h2>Add Player</h2>
        <PlayerForm onCreate={() => this.loadPlayers()}/>
        <hr></hr>
        <h2>Available Player</h2>
        {this.state.players.map(player => (
          <PlayCard player={player} key={player.id} />
        ))}
      </div>
    );
  }
}

export default PlayerPage;
import React, { Component } from 'react';
import axios from 'axios';
import {
  FormControl,
  FormGroup,
  FormLabel,
  Form,
  Button
} from 'react-bootstrap';

class PlayerForm extends Component {
  state = {
    name: '',
    nickname: ''
  };

  handleSubmit = e => {
    e.preventDefault();
    axios
      .post('http://localhost:3001/player', JSON.stringify(this.state), {
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json'
        }
      })
      .then(() => {
        this.props.onCreate();
      })
      .catch(err => console.log(err));
  };

  handelChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  render() {
    return (
      <Form onSubmit={this.handleSubmit}>
        <FormGroup>
          <FormLabel>Name</FormLabel>
          <FormControl
            type="text"
            name="name"
            placeholder="Enter player name"
            onChange={this.handelChange.bind(this)}
          />
        </FormGroup>
        <FormGroup>
          <FormLabel>Nickname</FormLabel>
          <FormControl
            type="text"
            name="nickname"
            placeholder="Enter player nickname"
            onChange={this.handelChange.bind(this)}
          />
        </FormGroup>
        <Button variant="btn btn-primary" type="submit">
          Add
        </Button>
      </Form>
    );
  }
}

export default PlayerForm;

I didn't check if the prop is present but normally you should.

How to handle API route

You should use environments variables:

.env

API_HOST=http://localhost:3001/
process.env.API_HOST

But it's depending on your development environment.

Answer:2

The lifecycle method componentDidMount() doesn't run in PlayerPage.js every time the state changes, just once when it first loads onto the page. This means the GET request is only run once when the page loads.

You need to either call the GET route again after a POST or DELETE happens, or update the app's state with the data from the POST/DELETE call when it happens to put that data onto the page as well as into the database.

Answer:3

To update the PlayerCard list, the players state must be updated in PlayerPage.

Since the parent has no way to get new players after the Rest API call, it seems that we need a callback function to update the parent component as a child.

Answer:4

In JQuery I know that there is a function called keydown, but this does allow me to set a timeout each time the callback is called. $(document).keydown(() => { //do stuff }); The //do stuff ...

In JQuery I know that there is a function called keydown, but this does allow me to set a timeout each time the callback is called. $(document).keydown(() => { //do stuff }); The //do stuff ...

I'm trying to get text to show up in an SVG element I created. I created a textNode and then appended that to a SVG text element, but it doesn't seem to be showing up. The SVG element is showing up ...

I'm trying to get text to show up in an SVG element I created. I created a textNode and then appended that to a SVG text element, but it doesn't seem to be showing up. The SVG element is showing up ...

I have a scrollable list and I would like to know when I've reached the end. Example: HTML: <ol> <li>a</li> <li>b</li> .... </ol> CSS: ol { ...

I have a scrollable list and I would like to know when I've reached the end. Example: HTML: <ol> <li>a</li> <li>b</li> .... </ol> CSS: ol { ...

  1. find your code iphone
  2. find your code name
  3. find your code
  4. find your code move data from android
  5. find your code ios
  6. find your code iphone setup
  7. find embed code youtube
  8. bible code find your name
  9. how to find your code generator on facebook
  10. find your code move to ios
  11. find tv code for youtube
  12. find out what tax code your on
  13. how to find your code on beem it
  14. how to find your code in bts world
  15. how to find your code on discord
  16. how to find your code on mario kart
  17. how to find your code on messenger
  18. how to find your code on facebook
  19. how to find your zip code
  20. how to find your code in steam

I have a little script at the bottom of the webpage with the following: <script language="Javascript"> var d = document.lastModified; var n = d.toLocaleString(); document.write("...

I have a little script at the bottom of the webpage with the following: <script language="Javascript"> var d = document.lastModified; var n = d.toLocaleString(); document.write("...