React - запрос Axios / Fetch / Ajax после того, как новые реквизиты переданы дочернему компоненту

У меня есть два компонента: приложение и ребенок. Моя цель состоит в том, чтобы приложение передавало идентификатор ребенку, и когда ребенок получает его в качестве реквизита, я хочу, чтобы ребенок выполнил запрос Axios / Fetch, а затем обновил себя данными результата. Я приму любой ответ, который предоставит мне пример исходного кода приложения / ребенка, который завершает мой пример или дает мне представление о том, действительно ли это возможно то, что я пытаюсь реализовать.

Я новичок в React.

// App.js

import React, { Component } from 'react';
import Child from './Child.js';
import './App.css';

class App extends Component {

  state = {
    id: 0
  };

  handleClick() {
    this.setState({
      id: this.state.id + 1
    });
  }

  render() {
    return (
      <div>
        <Child id = {this.state.id} />
        <div>
          <button onClick = {this.handleClick.bind(this)}>Pass new id down to Child component</button>
        </div>
      </div>
    );
  }
}

export default App;

// Child.js

import React, { Component } from 'react';
import axios from 'axios';

class Child extends Component {
    state = {
        data: null,
        id: 0
    };

    loadData(q, cb) {
        axios.get('http://localhost:3000/foo?q='+this.state.id)
        .then(result => {            
            // ?
            // this.setState would retrigger update and create an infinite updating loop
        })
        .catch(error => {
            console.info('error: ' + error);
        });
    }

    shouldComponentUpdate(nextProps, prevState) {
        console.info('shouldComponentUpdate: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));        

        // ??
    }

    getSnapshotBeforeUpdate(nextProps, prevState) {
        console.info('getSnapshotBeforeUpdate: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));

        // ?? 
    }

    static getDerivedStateFromProps(nextProps, prevState) {
        console.info('getDerivedStateFromProps: nextProps = ' + JSON.stringify(nextProps) + ', prevState = ' + JSON.stringify(prevState));
        return {
            id: nextProps.id
        };

        // ?? 
    }

    componentDidUpdate() {
        console.info('componentDidUpdate');
    }

  render() {
    return (
      <div>
          <div>data = {this.state.data}</div>
      </div>
    );
  }
}

export default Child;

В componentDidUpdate() сравните prevProps.id и this.state.id. Если они разные, позвоните в loadData(). (Я также не понимаю, как ваш ток мог создать бесконечный цикл?)

Chris G 08.09.2018 13:14

потому что loadData запускает setState, который в конечном итоге запускает componentDidUpdate

user3601578 24.10.2018 15:01

Но это еще не цикл. Чтобы это был цикл, componentDidUpdate() должен был бы всегда вызвать loadData(). Однако этого не происходит, только когда id был заменен. Прошло уже 7 недель, ты все еще зациклился на этом и даже не попробовал мое предложение?

Chris G 24.10.2018 16:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
3
1 158
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы должны вызвать check prev Id с текущим идентификатором, чтобы избежать рекурсивного обновления. Вам просто нужно убедиться, что вы получаете состояние из реквизита только в том случае, если ваши реквизиты изменились,

static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.id !== prevState.id) {
    return {
        id: nextProps.id
    };
 }
 return null;

}

Сообщите мне, если проблема не исчезнет

Если свойства изменились и состояние обновилось, вы вызовете loadData в componentDidUpdate.

Sakhi Mansoor 08.09.2018 13:25

почему там? он вызовет setState, который снова (и снова) обновит componentDidUpdate

user3601578 24.10.2018 15:02

Нет, вы ставите галочку в componentDidUpdate, чтобы избежать ненужных вызовов setState

Sakhi Mansoor 27.10.2018 23:56

Это может быть одним из способов решения вашей проблемы,

Во-первых, вам нужно обновить все данные о состоянии внутри вашего getDerivedStateFromProps.

static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.id !== prevState.id) {
    // Returning this object is equivalent to setting state using this.setState    
        return {
            id: nextProps.id
            data: loadData(nextProps.id) // Something like this
        };
    }
    return null; // Indicates no state change
}

Что касается вызова api внутри метода loadData, вы можете использовать aync / await для возврата данных из вызова api

async loadData(id) {
    try {
        // Make your api call here
        let response = await axios.get('http://localhost:3000/foo?q='+id);
        return await response.json();
    } catch(err) {
        // catches errors both in axios.get and response.json
        // Make sure to not update state in case of any error
        alert(err);
        return null;
    }
}

Примечание:

  • This is not the complete solution as you might want to not update the state in the case where your api call in loadData catches any error.
  • Also, since you are using api calls, you might want to limit the times pass props to the child cause they all will trigger different api calls and you will run into unpredictable states. Try debouncing.

Другие вопросы по теме