React Redux ведет себя странно

ниже мой редуктор и его результат. Результат очень странный. Переменная actions.pokemons: это массив, каждый элемент которого является объектом. Это значение присваивается a и копируется в b. Я не понимаю, почему b пустой массив. Кроме того, возвращаемое значение - пустой массив, состояние не обновляется?

const pokemons = (state=[], action) => {
    switch(action.type){
        case types.FETCH_POKEMON:
            var a = action.pokemons
            console.info(a)
            var b = [...action.pokemons]
            console.info(b)
            return a;

        default: return [...state];
    }
}

React Redux ведет себя странно

Это мой файл действий:

import * as types from '../constants/index';
import axios from 'axios'; 
export const actFetchPokemonsRequest = () => {
    return dispatch => {
        var result = [];
        for(var i=1; i<3; i++){
            axios({
                method: 'GET',
                url: `https://pokeapi.co/api/v2/pokemon/${i}`,
                data: null
            }).then(res => {
                // console.info(res.data)
                result.push(res.data)
                return dispatch(actFetchPokemon(result))
            }).catch(err => console.info(err))
        }
        return dispatch(actFetchPokemon(result))
    }
}

export const actFetchPokemon = pokemons => {
    return {
        type: types.FETCH_POKEMON,
        pokemons
    }
}

Я просто хочу проверить поведение оператора спреда

Huong Nguyen 31.03.2018 04:49

Я могу понять, что происходит. В консоли, когда a зарегистрирован, он пуст, пока вы не откроете его. Вот что происходит, когда результат при регистрации отличается от результата при фактическом запуске программы. Действие отправляется с помощью a, который пуст, он копирует его в b, который становится пустым, затем что-то позже по строке добавляет дополнительные элементы в a, что приводит к появлению дополнительных элементов в инструментах разработчика при расширении.

kingdaro 31.03.2018 04:50

Итак ... убедитесь, что товары есть перед отправкой?

kingdaro 31.03.2018 04:50

Можете ли вы добавить еще одну строку console.info (action.pokemons) перед назначением переменной a или b. Это прояснит, что происходит.

Sibaprasad Maiti 31.03.2018 04:55

@kingdaro - это последовательные инструкции, насколько это возможно. ты говоришь

RIYAJ KHAN 31.03.2018 04:55

@kingdaro, я не совсем понимаю вашу точку зрения, я добавляю свой файл действий для пояснения

Huong Nguyen 31.03.2018 05:05

@SibaprasadMaiti результат аналогичен первому сценарию. Я получаю массив с 2 объектами

Huong Nguyen 31.03.2018 05:08

После обновления с помощью файла действия вы, вероятно, захотите заменить цикл на Promise.all и сопоставить массив Promises. Есть сочетание асинхронного и синхронного кода.

thgaskell 31.03.2018 05:08

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

Sibaprasad Maiti 31.03.2018 05:26
Поведение ключевого слова "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) для оценки ваших знаний,...
0
9
156
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

  1. Вы создаете пустой массив с именем result
  2. Вы запускаете цикл for, и каждый цикл ЗАПУСКАЕТ обещание, вы достигаете конца цикла for перед, любое обещание разрешено. Цикл заканчивается очень быстро, и ваш код переходит к следующему оператору.
  3. В вашем операторе возврата вы вызываете отправку, передающую действие, которое получает массив. Вы попадаете сюда сразу после цикла for, и поскольку ни одно из обещаний не разрешено, ваш result пуст.

Это можно сделать следующим образом:

import * as types from '../constants/index';
import axios from 'axios'; 

export const actFetchPokemonsRequest = () => {      
    return dispatch => {
      const pokemonRequests = [
        axios({ method: 'GET', url: 'https://pokeapi.co/api/v2/pokemon/0', data: null }),
        axios({ method: 'GET', url: 'https://pokeapi.co/api/v2/pokemon/1', data: null }),
        axios({ method: 'GET', url: 'https://pokeapi.co/api/v2/pokemon/2', data: null }),
      ];

      Promise.all(pokemonRequests).then((responses) => {
        const dataArr = responses.map(r => r.data);

        dispatch(actFetchPokemon(dataArr));
      });
    }
}

export const actFetchPokemon = pokemons => {
  return {
    type: types.FETCH_POKEMON,
    pokemons,
  }
}

В вашем сокращении у вас будет просто:

const pokemons = (state = [], action) => {
  switch(action.type){
    case types.FETCH_POKEMON:
      return [...action.pokemons];
      // Or if you want to simply extend what you currently have
      // return [...state, ...action.pokemons];
    default:
      return state;
  }
}

Если вдаваться в подробности асинхронной части, происходит то, что вы запускаете все свои запросы axios. Но вы хотите подождать, пока ВСЕ они разрешатся, здесь вам пригодится Promise.all. Promise.all ожидает разрешения всех обещаний, а затем объединяет в массив ответ (если есть) каждого обещания. Таким образом я могу использовать на нем .map и фактически извлекать поле data из каждого ответа на запрос. Как только я закончу со всем этим, я наконец могу отправить свое действие, теперь передавая действительный массив данных. По Promise.all есть много документации, поэтому я бы рекомендовал взглянуть на нее.

Надеюсь, это поможет с вашей проблемой, дайте мне знать, если это не сработает для вас.

ПРИМЕЧАНИЕ: для простоты я вручную записал все запросы, но есть много лучших способов сделать это динамически.

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