В настоящее время я пытаюсь отправить массив своему редуктору и установить его в своем состоянии, чтобы использовать его в компоненте. Он отлично работает с объектами, но я не могу понять, как это сделать с массивом.
Создатель моего действия:
export const loadUserItems = () => {
return async function(dispatch) {
const url_current = 'https://whateverapi';
const response = await axios.get(url_current);
const items = response.data.items;
dispatch(loadItems(items));
}
}
function loadItems(data) {
return {
type: LOAD_USER_ITEMS,
payload: data
};
}
Поэтому, если я получу один элемент в моем массиве, он будет работать отлично. Я могу установить его как объект в моем редукторе и использовать его в своем компоненте.
Мой редуктор:
import {
LOAD_USER_ITEMS
} from '../actions/types';
const INITIAL_STATE = {
items: []
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case LOAD_USER_ITEMS :
return {
items: action.payload
};
default:
return state;
}
};
Итак, action.payload - это массив, я могу console.info, и он выводит мне массив. Этот массив содержит несколько объектов JSON.
Но когда я пытаюсь получить к нему доступ в своем компоненте, он сообщает мне, что он не определен.
import ... (no problems here)
class HomePage extends Component {
loadUserItems() {
this.props.loadUserItems();
}
constructor(props) {
super(props);
this.loadUserItems();
}
render() {
return (
<Container>
<Content>
<View style = {styles.headerViewStyle}>
<Image
style = {styles.headerImageStyle}
source = {require("../assets/images/header.png")}
/>
</View>
<View>
<ItemSquareDisplay description = {this.props.items[0].type}/>
</View>
</Content>
</Container>
);
}
}
const mapStateToProps = state => {
return {
items: state.items.items,
};
};
export default connect(mapStateToProps, {loadUserItems}) ( HomePage );
Мой массив содержит элементы, первый элемент. Тип - «Холодильник» ... Но он говорит мне, что this.props.items [0] .type не определен. Я сделал то же самое, но только что отправил первый элемент, и он работал нормально, я мог получить доступ к this.props.items.type. Но, похоже, это не сработает, если я отправлю весь массив.
Вам нужно еще раз, ребята! Спасибо



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Причина в том, что вы обращаетесь к пустому массиву.
Первоначально ваш массив элементов представляет собой пустой массив внутри редуктора. Теперь внутри вашего компонента вы вызываете действие loadUserItems, которое потребует значительного времени для получения данных и обновления хранилища redux. В течение этого периода времени выполняется метод рендеринга вашего компонента и пытается получить доступ к 1-му элементу пустого массива, что определенно выдаст ошибку.
Итак, что вы могли бы легко сделать, так это проверить, не пуст ли массив, прежде чем обращаться к его элементам.
<ItemSquareDisplay description = {this.props.items && this.props.items.length > 0 ? this.props.items[0].type : ''} />
Обратите внимание, что причина для работы при использовании объекта заключается в том, что, к счастью, действие обновило хранилище redux до выполнения метода рендеринга и доступа к массиву.
Хорошо, готово и работает. Большое спасибо за этого приятеля, потратить последние 4 часа, пытаясь понять это. Теперь мне нужно исправить это везде в моем коде. Знаете ли вы, что другой человек ожидает этого поведения, чтобы не проверять все объекты, которые я получаю от API?
Фактически this.props.items используется для проверки того, определена ли переменная с именем item. Это дополнительная проверка, чтобы избежать вызова .length неопределенного массива.
Следует использовать неизменяемые переменные в редукторе.
Вы можете использовать slice() или concat()
В твоем случае:
case LOAD_USER_ITEMS :
return {
items: action.payload.slice()
};
или если вы хотите добавлять больше предметов при каждой загрузке после
case LOAD_USER_ITEMS :
return {
items: state.items.concat(action.payload)
};
убедитесь, что полезная нагрузка - это массив
Должен ли я проверять, существует ли массив элементов (см. Последний ответ) с помощью slice () в моем компоненте? Мне нужно будет добавить элементы в массив, поэтому спасибо за эти методы.
В этом случае срез просто создаст копию массива. Его не нужно использовать в компоненте (в строке из ответа превью).
Вы можете использовать просто оператор распространения. return {items: [... state.items, ... action.payload]};
Я жду свой поезд, попробуй через несколько минут.