Как мне выполнить цикл через массив в объекте `this.state`?

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть GET запрос на выборку данных, данные содержат object а затем array в object . Затем я использую this.setState и теперь имею array , в object , в object

Проблема в том, что когда я пытаюсь выполнить цикл по массиву, я не могу, так как получаю

TypeError: this.state.games.games is undefined

Если у меня есть только this.state.games , и я пытаюсь выполнить цикл, я получаю

TypeError: this.state.games.forEach is not a function

Я решил это с помощью try...catch метода, однако я чувствую, что это не лучший способ решить эту проблему.

 class HomePage extends Component {
    constructor(props) {
        super(props)
        this.state = {games: []}
    }

    componentDidMount() {
        axios.get(`http://localhost.com:5000/user/games`, {withCredentials: true})
            .then(res => {
                const games = res.data;
                this.setState({ games })
            })
    }

    render() {
        const games = [];

        try {
            this.state.games.games.forEach(function (game, index) {
                console.log(index) // index
                console.log(game) // value

                games.push(
                    <Grid.Column>
                        <MyGames key={index} game={{title: game.title, description: game.genre, thumbnail: game.thumbnail}}/>
                    </Grid.Column>
                )

            })
        }
        catch( e ) {
            console.log("Error: "   e );
        }

        return (
            <div>
                <Grid columns={1}>

                    <Grid.Column>
                        <FriendsList/>

                        <Header as='h3'>My Games</Header>
                        <Grid columns={4} container={'true'} padded>
                                {games}
                        </Grid>
                    </Grid.Column>
                </Grid>
            </div>
        )
    }
}
  

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

ОБНОВЛЕНИЕ: Проблема была с const game = res.data , поскольку это был объект, это вызывало проблему с объектом в объекте. Изменение его на res.data.games устранило проблему, так как .games в данных указан массив.

Комментарии:

1. Что такое res.data ? Вероятно, это не массив?

2. @JonasWilms Да, вы правы! Это был объект, поэтому я просто изменил его на res.data.games , и это сработало! Спасибо @JLRishe за объяснение

Ответ №1:

Вы пытаетесь выполнить цикл this.state.games.games , но в вашем конструкторе начальное значение, которое вы задаете, state равно { games: [] } . Следовательно, this.state.games.games изначально не является массивом, и именно поэтому вы получаете сообщение об ошибке.

Два способа исправить.

Инициализируйте свое состояние структурой, которая отражает способ доступа к состоянию:

 this.state = { games: { games: [] } };
  

Или, возможно, лучшая идея, измените свой код так, чтобы ваш массив был this.state.games , а не this.state.games.games :

 .then(res => {
    const games = res.data.games;
    this.setState({ games })
})

// further below ...

this.state.games.forEach(function (game, index) {
  

Комментарии:

1. вам нужно понять, что запрашивает OP, ПРЕЖДЕ чем отправлять ответ

2. @CrisimIlNumenoreano Я понимаю, о чем спрашивает OP, и я вижу, что не так с их кодом. Вот почему я опубликовал ответ. Спасибо за ваш комментарий.

3. извините, я не хотел быть грубым с вами. проблема в том, что внутри res.data как джонас прокомментировал ранее.

4. @JLRishe Ах!! Я должен это видеть! Теперь это работает, спасибо за вашу помощь 🙂

Ответ №2:

Изменить

         this.state.games.games.forEach(function (game, index) {

        })
  

Для

         this.state.games.forEach(function (game, index){

        })
  

Ответ №3:

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

   //your render method 
render() {
    const games = [];
      if(this.state.games.games.length<=0){
       return <h1>Please wait while loading data</h1>
      }
    try {
        this.state.games.games.forEach(function (game, index) {
            console.log(index) // index
            console.log(game) // value

            games.push(
                <Grid.Column>
                    <MyGames key={index} game={{title: game.title, description: game.genre, thumbnail: game.thumbnail}}/>
                </Grid.Column>
            )

        })
    }
    catch( e ) {
        console.log("Error: "   e );
    }

    return (
        <div>
            <Grid columns={1}>

                <Grid.Column>
                    <FriendsList/>

                    <Header as='h3'>My Games</Header>
                    <Grid columns={4} container={'true'} padded>
                            {games}
                    </Grid>
                </Grid.Column>
            </Grid>
        </div>
    )
}
  

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

Комментарии:

1. Это скорее комментарий, чем ответ. Решение с кодом было бы неплохо