Возврат html из fetch() и показ пользователю

Я делаю вызов API, используя fetch().then()...

Получение ответа с помощью application/json, и я хочу сохранить данные из ответа внутри тегов html, вернуть их и показать пользователю.

Из API я получаю 25 результатов, но мне нужны только первые 6 (сделано это с помощью цикла for).

Что внутри console.info() Я хочу показать в коде, где комментарий «Результат должен быть здесь».

Могу ли я и как это сделать?

Код ниже.

Я хочу использовать его в Stateless/Functional Component, поэтому без обработки состояния.

Кстати. Я новичок во всем этом, поэтому, пожалуйста, будьте нежны. Спасибо!

const Related = props => {
  const url = `/artist/${props.artistId}/related`;

  const getRelatedArtists = () => {
    fetch(url)
      .then(res => res.json())
      .then(res => {
        var artist, name, numFans, img;
        for (let i = 0; i < 6; i++) {
          artist = res.data[i];
          name = artist.name;
          numFans = artist.nb_fan;
          img = artist.picture;
          console.info(`
            <div>
              <p>Name: ${name}</p>
              <p>Fans: ${numFans}</p>
              <img src=${img} alt=${name} />
            </div>
          `);
        }
      })
      .catch(err => console.info(err));
  };

  return (
    <div>
      <p>Related artists</p>
      <button onClick = {getRelatedArtists}>get</button>
      {/* Result should be here */}
    </div>
  );
};

Результат, который я хочу, выглядит так: https://imgur.com/40dUyiw

Возможный дубликат В React, как показать данные из API в таблице HTML?

Sunil Chaudhary 07.04.2019 11:50

@Sunil спасибо, например, но я хочу использовать его без состояния. Если это возможно (?)

zrna 07.04.2019 11:57

Вы должны использовать либо состояние, либо хранилище. Если вы используете функциональный компонент, вы можете отправить действие редьюсеру, обновляющему ваш магазин (когда ваш вызов API завершен). Обновление магазина повторно отобразит пользовательский интерфейс с новыми данными. В более новых версиях реакции вы можете реагировать хуки, чтобы добиться того же внутри компонентов без сохранения состояния.

Sunil Chaudhary 07.04.2019 12:03

@Sunil да, я попробую с крючками

zrna 07.04.2019 12:24
Поведение ключевого слова "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) для оценки ваших знаний,...
4
4
5 356
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

React очень сильно зависит от состояние и реквизит — либо реквизиты прошедший для компонента, либо внутреннее состояние поддерживается на единицу. В вашем примере, не зная подробностей, похоже, что единственным вариантом здесь будет использование состояние компонента. Это означает, что вы не можете использовать компонент без состояния, как минимум, вы будете смотреть на PureComponent или Component, т.е.

import React, { PureComponent } from 'react';

class Related extends PureComponent {
  state = {
    artists: null,
    error: null
  }

  constructor(props) {
    this.super();
    this.url = `/artist/${props.artistId}/related`;
  }

  getRelatedArtists = async () => {
    try {
      const res = await fetch(this.url);
      const json = await res.json();
      this.setState({ artists: json.data, error: null });
    } catch(e) {
      console.error(e);
      this.setState({ error: 'Unable to fetch artists' });
    }
  }

  renderError() {
    if (!this.state.error) return null;

    return (
      <span className = "error">{this.state.error}</span>
    )
  }

  renderArtistList() {
    if (!this.state.artists) return null;

    return this.state.artists.map((x,i) => (
      <div key = {i}>
        <p>Name: ${x.name}</p>
        <p>Fans: ${x.nb_fans}</p>
        <img src=${x.picture} alt=${name} />
      </div>
    ));
  }

  render() {
    return (
      <div>
        <p>Related artists</p>
        <button onClick = {this.getRelatedArtists}>get</button> {this.renderError()}
        {this.renderArtistList()}
      </div>
    );
  }
}

Если вы используете React 16.x, вам, возможно, следует подумать об использовании Хуки. Вот как это будет выглядеть как функциональный компонент

import React, { useState, useCallback } from 'react';

function Related(props) {
  // setup state
  const [artists, setArtists] = useState(null);
  const [error, setError] = useState(null);
  // setup click handler
  const getRelatedArtists = useCallback(async () => {
   try {
      // fetch data from API
      const res = await fetch(`/artist/${props.artistId}/related`);
      const json = await res.json();
      // set state
      setArtists(json.data);
      setError(null);
    } catch(e) {
      console.error(e);
      setError('Unable to fetch artists');
    }
  }, [props.artistId]);
  // setup render helper
  function renderArtist(artist, key) {
    return (
      <div key = {key}>
        <p>Name: ${artist.name}</p>
        <p>Fans: ${artist.nb_fans}</p>
        <img src=${artist.picture} alt=${artist.name} />
      </div>
    );
  }
  // render component
  return (
    <div>
      <p>Related artists</p>
      <button onClick = {getRelatedArtists}>get</button> {error}
      {artists && artists.map(renderArtist)}
    </div>
  )
}

Привет @James, спасибо за помощь. Я включаю этот код с хуками React и получаю ошибку: Uncaught TypeError: artist.map не является функцией. что теперь? Вы можете объяснить это мне?

zrna 07.04.2019 12:23

@Zrna как выглядит ответ сервера? Я предположил, что вы получаете список JSON, но, похоже, это не так.

James 07.04.2019 12:27

@Zrna Zrna а, хорошо, вижу, что полезная нагрузка не совсем то, что я ожидал, похоже, у вас есть ответ на страницу. Я обновился, чтобы соответствовать.

James 07.04.2019 13:05

Чувак, ты для меня спасатель. Это работает. Большое спасибо!

zrna 07.04.2019 13:25

при использовании реакции, поэтому вам нужно использовать преимущества, которые предоставляет вам реакция, вы должны разделить свой код и сделать его пригодным для повторного использования.

во-вторых: для получения всего нескольких чисел из связанных сообщений из большого массива вам не нужно делать цикл, вы можете просто объявить переменную и сохранить в ней количество сообщений, которые вам нужно сохранить в ней

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

class RelatedPosts extends Component{
    state = {
        realted: [],
    }
    componentDidMount(){
        const url = `/artist/${props.artistId}/related`;
        fetch(url)
            .then(response=>{
                const relatedPosts = response.data.slice(0 ,4),
                    latestRelatedPosts = relatedPosts.map(post=>{
                        return {
                            post
                        }
                    })
                ;
                this.setState({
                    realted: latestRelatedPosts
                });
            }).catch(error=>{
                console.info(error)
            })
    }
    render() {
        let relatedPosts = this.state.realted.map(realtedPost=>{
            return (
                <Post post = {realtedPost}/>
            );
        });
        return (
            <section className = "Posts">
                <p>Related artists</p>
                {relatedPosts}
            </section>
        );
    }
}
export default RelatedPosts;

здесь я создал запрос в componentDidMount Lifecycle, потому что он вызывается сразу после того, как компонент вставлен в дерево, и вы можете найти дополнительную информацию здесь

и здесь я создам новый компонент, чтобы упростить код для обслуживания позже, если вы захотите что-то изменить позже, и я передам ему данные, которые приходят из ответа на мой запрос

import React from 'react';
const post = (props) => (
    <article className = "relatedPost">
        <h1>Name: {props.post.Name}</h1>
        <h1>Fans: {props.post.numFans}</h1>
        <img src = {img} alt = {name} />
    </article>
);
export default post

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