我无法从this.state

时间:2019-12-09 16:11:39

标签: javascript reactjs axios

我从后端接收到JSON,我将其保存为我的状态,并且想在其他react组件的props中使用它,但是它不起作用。

我尝试在组件的{this.state.movies["0"]["title"]}道具中显示类似的需要日期,但这没用。

  constructor() {
    super();
    this.state = {
      movies: []
    }
  }

  componentDidMount() {
    this.getAllMoviesForMainPage();
  }

  getAllMoviesForMainPage() {
    axios.get("http://localhost:8080/showAll")
      .then(response => {
        this.setState({ movies: response.data })
      })
  }

  render() {
    return (
      <div className="qwerty">
        <MainPageComponent />
        <div className='moviePreviewGrid'>
          <Router>
            <div className="moviePreviewGrid-row">
              <div className="moviePreviewGrid-col">
                <MoviePreview
                  Title={this.state.movies["2"]["title"]}
                  MoviePreviewAvatar={DrivePoster}
                  SeeMore="unrelated long string here"
                />
                <NavLink to="/showByTitle/Драйв">
                  <button type="button" className="myBtn">See more</button>
                </NavLink>
              </div>

和我的JSON结构

[
    {
        "id": 1,
        "title": "Джокер",
        "releaseDate": "2019",
        "genre": "Триллер, драма, криминал",
        "duration": "122 минуты",
        "rating": 8.7,
        "criticReviews": [
            {
                "criticName": "Anton",
                "review": "anton review"
            },
            {
                "criticName": "OldCritic",
                "review": "old review"
            }
        ],
        "userReviews": [
            {
                "nickName": "Igor",
                "review": "igor review"
            },
            {
                "nickName": "Nik",
                "review": "nik review"
            }
        ]
    },
    {
        "id": 2,
        "title": "Ирландец",
        "releaseDate": "2019",
        "genre": "Драма, триллер, криминал, биографический",
        "duration": "209 минут",
        "rating": 8.4,
        "criticReviews": [
            {
                "criticName": "YoungCritic",
                "review": "young review"
            }
        ],
        "userReviews": [
            {
                "nickName": "Gambit",
                "review": "gambit review"
            },
            {
                "nickName": "Andrew",
                "review": "andrew review"
            }
        ]
    },
    {
        "id": 3,
        "title": "Драйв",
        "releaseDate": "2011",
        "genre": "Боевик, драма",
        "duration": "100 минут",
        "rating": 7.8,
        "criticReviews": [
            {
                "criticName": "Critic",
                "review": "review"
            }
        ],
        "userReviews": [
            {
                "nickName": "Anton",
                "review": "anton review"
            }
        ]
    },
    {
        "id": 4,
        "title": "Последний человек на Земле",
        "releaseDate": "2015",
        "genre": "Комедия",
        "duration": "22 минуты",
        "rating": 7.3,
        "criticReviews": [
            {
                "criticName": "NewCritic",
                "review": "new review"
            }
        ],
        "userReviews": [
            {
                "nickName": "Atomf7",
                "review": "atomf7 review"
            }
        ]
    },
    {
        "id": 5,
        "title": "Интерстеллар",
        "releaseDate": "2014",
        "genre": "Фантастика, драма, приключения",
        "duration": "169 минут",
        "rating": 8.6,
        "criticReviews": [
            {
                "criticName": "Nik",
                "review": "nik review"
            }
        ],
        "userReviews": [
            {
                "nickName": "Alice",
                "review": "alice review"
            }
        ]
    }
]

而且我不会有第一部电影的标题

3 个答案:

答案 0 :(得分:2)

在第一个init中,this.state.movies的长度为0,因此this.state.movies["2"]["title"]当然毫无价值 因为getAllMoviesForMainPage async (异步),并且需要花费更长的时间才能完成,所以首先您必须给它一个初始值,只有在请求完成后才可以给它实际值。

示例:

<MoviePreview
  Title={this.state.movies.length > 0 ? this.state.movies[2].title : ""}
  MoviePreviewAvatar={DrivePoster}
/>

在这种情况下,通常使用状态isLoading。这样您就可以知道何时收到数据。

答案 1 :(得分:1)

您正在componentDidMount的{​​{1}}中发出GET请求,因此在async中解决承诺之前,您的状态在.then(..中不包含response.data

要记住的重要一点是,每次执行movies时,组件都会重新渲染,因此在执行this.setState(..方法中的setState之前,将进行初始渲染,并且其中将包含一个空数组在您在构造函数中定义的getAllMoviesForMainPage

此外,由于您的响应包含对象数组,因此您将使用this.state.movies而不是movies['2'].title

因此,您的render方法应包含以下内容以显示电影预览:

movies['2']['title']

<div className="moviePreviewGrid-col"> {this.state.movies.length ? ( <MoviePreview Title={this.state.movies['2'].title} MoviePreviewAvatar={DrivePoster} SeeMore="unrelated long string here" /> ) : ( <PlaceHolderPreview /> )} <NavLink to="/showByTitle/Драйв"> <button type="button" className="myBtn"> See more </button> </NavLink> </div> 可能是您将显示的另一个组件-很好的预览占位符。

希望这一切都有道理。

答案 2 :(得分:1)

在第一个渲染电影中,尚未从api中获取电影。

所以您需要有条件地渲染它。

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

export default class Test extends Component {
  constructor() {
    super();
    this.state = {
      movies: [],
      loading: true
    }
  }

  componentDidMount() {
    this.getAllMoviesForMainPage();
  }

  getAllMoviesForMainPage() {
    axios.get("http://localhost:8080/showAll")
      .then(response => {
        this.setState({ movies: response.data, loading: false })
      })
  }

  render() {
    const { loading, movies } = this.state;

    if (loading) {
      return <div>Loading...</div>;
    } else {
      return (
        <div>
          {movies.length > 0 ? (
            <div>First movie title: {movies[0].title}</div>
          ) : (
            <div>No movies</div>
          )}
        </div>
      );
    }
  }
}

您可以使用伪造的api来检查此example