Как сделать несколько запросов ax ios .get () с помощью componentDidMount () и назначить значение ответа от 1 до 2? - PullRequest
0 голосов
/ 04 мая 2020

Я пытаюсь создать веб-приложение с Wordpress REST API.

Я делаю первоначальный запрос GET к конечной точке и анализирую res.data, чтобы получить некоторые значения. Но одно из значений featured_media является параметром для второго запроса GET, который я пытаюсь выполнить. Мне трудно вывести это значение из этого состояния во второй запрос GET.

Вот состояния.

state = {
        graduatepost: {},
        category: '',
        featured_media: '',
        imgURL: '',
        isLoaded: false
    }

Вот componentDidMount()

componentDidMount() {
        const { featured_media } = this.props;

        axios.get(`http://localhost:8000/wp-json/wp/v2/blog/${this.props.match.params.id}`)
            .then(res => this.setState({
                graduatepost: res.data,
                category: res.data.categories[0],
                featured_media: res.data.featured_media,
                isLoaded: true
            }))
            .catch(err => console.log(err));

        const getImageURL = axios.get(`http://localhost:8000/wp-json/wp/v2/media/${featured_media}`);

        Promise.all([getImageURL]).then(res => {
            this.setState({
                imgURL: res[0].data.media_details.sizes.full.source_url,
                isLoaded: true
            });
        });
    }

1-й GET-запрос: http://localhost:8000/wp-json/wp/v2/blog/${this.props.match.params.id}

2-й GET-запрос : http://localhost:8000/wp-json/wp/v2/media/${featured_media}

Как видите, для 2-го запроса требуется значение featured_media, которое находится в ответе на 1-й запрос GET.

Я представляю компонент следующим образом.

render() {
        const { graduatepost, category, isLoaded, featured_media, imgURL } = this.state;
        if(isLoaded) {
            return (
                <Styles>
                    <Fragment>
                        <Link to='/graduate-posts'>Go Back</Link> // Ignore this
                        <hr />
                        <h1>{graduatepost.title.rendered}</h1>
                        <div dangerouslySetInnerHTML={{__html: graduatepost.content.rendered}}></div>
                        <h4>Category: {category}</h4>
                        <h4>featured_media: {featured_media}</h4>
                        <h4>imgURL: {imgURL}</h4>
                    </Fragment>
                </Styles>
            )
        }
        return <h3>Loading...</h3> // Ignore this
    }

Когда я выполняю рендеринг компонента. Существует ошибка консоли 404 для второго запроса GET, в которой говорится.

GET http://localhost:8000/wp-json/wp/v2/media/undefined 404 (Not Found)
Uncaught (in promise) Error: Request failed with status code 404
    at createError (createError.js:16)
    at settle (settle.js:17)
    at XMLHttpRequest.handleLoad (xhr.js:61)

Я предполагаю, что это потому, что featured_media пусто / не определено, но я не могу понять, как извлечь это значение из первого запроса GET, ответа.

Это может показаться очевидным, но я относительно новичок в совместной работе с React. js и API. Ваша помощь будет принята с благодарностью.

Спасибо.

Ответы [ 4 ]

1 голос
/ 04 мая 2020

Вы пробовали функцию Asyn c? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

async componentDidMount() {
        ....
        await axios.get ...
        ....
}
0 голосов
/ 04 мая 2020

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

Приложение. js

class App extends React.Component {
    render() {
        return (
            <Router>
                <div>
                    <ul>
                        <li>
                            <Link to="/">Home</Link>
                        </li>
                        <li>
                            <Link to="/posts">Posts</Link>
                        </li>
                    </ul>
                    <hr/>
                    <Switch>
                        <Route exact path="/">
                            <UserList/>
                        </Route>
                        <Route path="/posts">
                            <PostListPageByUser/>
                        </Route>
                    </Switch>
                </div>
            </Router>
        );
    }
}
export default App;

Компонент UserList

import React from 'react';
import axios from 'axios';
import PostListPageByUser from "./PostListPageByUser";
import {withRouter} from "react-router-dom";

class UserList extends React.Component {
    state = {
        users: [],
        showPostList: false,
        user: {}
    };

    componentDidMount() {
        axios.get(`https://jsonplaceholder.typicode.com/users`)
            .then(res => {
                const users = res.data;
                console.log(users);
                this.setState({users});
            })
    }

    handleClick = (user) => {
        console.log(user);
        this.setState({showPostList: true, user: user});
        this.props.history.push({
            pathname: '/posts',
            user: user
        });
    };

    render() {
        return (
            <div>
                <ul>
                    {this.state.users ? this.state.users.map(user => <div key={user.id}>
                        <span style={{minWidth: 400}}>{user.name} </span>
                        <button onClick={() => {
                            this.handleClick(user)
                        }}>See Posts
                        </button>
                    </div>) : null}
                </ul>
                {this.state.showPostList ? <PostListPageByUser user={this.state.user}/> : null}
            </div>
        )
    }
}

export default withRouter(UserList);

Компонент PostListByUser

import React from "react";
import axios from 'axios';
import {withRouter} from "react-router-dom";

class PostListPageByUser extends React.Component {
    signal = axios.CancelToken.source();
    state = {
        posts: [],
    };

    componentDidMount() {
        if(!this.props.location.user){
            alert('Please click see posts button');
            this.props.history.push('/');
            return;
        }
        axios.get(`https://jsonplaceholder.typicode.com/posts?userId=${this.props.location.user.id}`, {
            cancelToken: this.signal.token,
        })
            .then(res => {
                this.setState({posts: res.data});
                console.log(res.data, 'Posts');
            }).catch(err => {
            console.log(err);
        });
    }

    render() {
        return (
            <div>
                <ul>
                    {
                        this.state.posts ? this.state.posts.map(post => <li key={post.id}>{post.title}</li>) : null
                    }
                </ul>
            </div>
        )
    }
}

export default withRouter(PostListPageByUser);
0 голосов
/ 04 мая 2020

Лучший способ немедленного доступа к установленным данным - использовать callback.

this.setState принять обратный вызов в качестве второго аргумента (setState(updater, [callback])), , поэтому мы должны сделать наш второй запрос в нашем callback утверждении.

Ваш код должен выглядеть примерно так:

axios
  .get(`http://localhost:8000/wp-json/wp/v2/blog/${this.props.match.params.id}`)
  .then((res) =>
    this.setState(
      {
        graduatepost: res.data,
        category: res.data.categories[0],
        featured_media: res.data.featured_media,
        isLoaded: true,
      },
      () =>
        axios
          .get(
            `http://localhost:8000/wp-json/wp/v2/media/${this.state.featured_media}`
          )
          .then((res) => {
            this.setState({
              imgURL: res[0].data.media_details.sizes.full.source_url,
              isLoaded: true,
            })
          })
    )
  )
  .catch((err) => console.log(err))
0 голосов
/ 04 мая 2020

Возможно запросить его в ответе от 1-го axios.get. Причина, по которой он не работает, заключается в том, что this.setState - это асинхронная c функция в React, поэтому undefined при доступе к ней сразу ниже.

Попробуйте что-то вроде:

axios.get(`http://localhost:8000/wp-json/wp/v2/blog/${this.props.match.params.id}`)
  .then((res) => {
    const state = {
             graduatepost: res.data,
             category: res.data.categories[0],
             featured_media: res.data.featured_media,
             isLoaded: true
    }
    this.setState(state)
    return axios.get(`http://localhost:8000/wp-json/wp/v2/media/${state.featured_media}`);
  })
  .then((res) => {
    // do something with res
  })
  .catch((err) => {
    // handle err
  });
...