Почему мой компонент не обновляется после отправки данных в службу REST - PullRequest
2 голосов
/ 13 января 2020

Итак, я пытаюсь создать свое первое приложение реакции. js и мне интересно, почему моя страница не обновляется после размещения нового игрока в моем приложении через топор ios и после УДАЛЕНИЯ. Как я переосмыслил sh страницу, после которой игроки создаются или исчезают в зависимости от операции. Так что часть API работает просто отлично.

У меня есть PlayerPage. js примерно так:

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;

Он ссылается (и заполняется из API) на компонент PlayerForm и PlayerCard, который выглядит следующим образом:

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;

и 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;

Итак, вопрос в том, почему моя сторона не обновляется должным образом? Я благодарен за любые подсказки. Заранее спасибо.

Бонусный вопрос : Как динамически получить ip и порт в зависимости от того, где работает сервер узла?

Ответы [ 5 ]

4 голосов
/ 13 января 2020

Почему это не работает:

Поскольку вы не обновляете представление списка при отправке формы. Реакция не магическая c, вам нужно указать, когда вы хотите, чтобы представление было перерисовано.

Одним из способов является добавление onCreate реквизита к вашей playerform.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: []
  };

  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;

Я не проверял наличие опоры, но обычно вы должны.

Как обрабатывать маршрут API

Вы должны использовать переменные окружения:

.env

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

Но это зависит от вашей среды разработки.

2 голосов
/ 13 января 2020

Как и предполагалось, вы не обновляете состояние компонента PlayerPage. Даже если ответ, предложенный @ tristan , работает, я бы посоветовал максимально сократить вызовы API. Мое решение будет следующим:

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);
  }

  handleAddNewPlayer = player => {
    this.setState(prevState => ({
      players: [...prevState.players, player] // or [player, ...prevState.players]
    }))
  }

  handleRemovePlayer = id => {
    const players = this.state.filter(player => player.id !== id)
    this.setState({ players })
  }

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

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(data => this.props.handleAddNewPlayer(data)) // adjust this api call to return added user with id
      .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;

и 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(this.props.handleRemovePlayer(this.player.id))
      .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;
0 голосов
/ 13 января 2020

Я предполагаю, что вы не используете какой-либо инструмент управления состоянием (Redux, Flux), и только реагирует, и вы не хотите снова вызывать API. Внутри компонента PlayerPage сделать функцию

addPlayer=(player)=>{
this.setState({
players: {...players, player}
})
}
}

и при рендеринге того же компонента

Inside PlayerCard

handleClick() {
    axios
      .delete(`http://localhost:3001/player/${this.player.id}`)
      .then((response)=>{
you get your output pass it to props
var player=response.data
this.props.addPlayer(response)
    })
      .catch(console.log);
  }

Этот пример только со ссылкой на addPlayer. Вы можете настроить его в соответствии с вашими требованиями

0 голосов
/ 13 января 2020

Чтобы обновить список PlayerCard, состояние игроков должно быть обновлено в PlayerPage.

Поскольку родительский объект не может получить новых игроков после вызова API Rest, похоже, для обновления нам нужна функция обратного вызова родительский компонент как дочерний.

0 голосов
/ 13 января 2020

Метод жизненного цикла componentDidMount() не запускается в PlayerPage.js каждый раз, когда изменяется состояние, только один раз, когда он впервые загружается на страницу. Это означает, что запрос GET запускается только один раз при загрузке страницы.

Вам необходимо либо повторно вызвать маршрут GET после того, как произойдет POST или DELETE, либо обновить состояние приложения с помощью данных из вызова POST / DELETE. когда это происходит, чтобы поместить эти данные на страницу, а также в базу данных.

...