Я пытаюсь добавить функциональность к кнопкам в списке моего приложения, чтобы при нажатии кнопки UP элемент списка менялся местами с элементом прямо поверх него.
Я пробовал использовать функцию как ценить моего состояния в setState. Но когда я нажимаю кнопку, возникает эта ошибка:
TypeError: Cannot read property 'map' of undefined
App.render
src/App.js:49
46 | return(
47 | <div>
48 | <h1>UNUM Challenge</h1>
> 49 | <ol>
| ^ 50 | {this.state.shoppingList.map((item, index) =>
51 | (<li data-index = {index} key = {index}>
52 | {item}
Что здесь происходит? Разве я не могу использовать функцию в качестве значения при такой настройке своего состояния?
this.setState({
shoppingList: arraymove(shoppingList, currentIndex , currentIndex - 1)
})
Вот полный код:
import React, { Component } from 'react';
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
}
class App extends React.Component {
constructor(props){
super(props);
this._handleItemSort = this._handleItemSort.bind(this);
this.state = {
shoppingList: ['Bananas', 'Apples', 'Rice', 'Eggs' , 'GTX 1080Ti', 'Avocado']
}
}
_handleItemSort(dir, currentIndex) {
// create new list of items from a spread of our current shoppingList state.
// we don't want to reference the actual state and mutate it! ?
const shoppingList = [...this.state.shoppingList]
if (dir === "up" ){
this.setState({
shoppingList: arraymove(shoppingList, currentIndex , currentIndex - 1)
})
}
}
render() {
return(
<div>
<h1>UNUM Challenge</h1>
<ol>
{this.state.shoppingList.map((item, index) =>
(<li data-index = {index} key = {index}>
{item}
<div className='controls'>
<button
disabled = {index === 0}
onClick = { () => this._handleItemSort("up", index) }>UP</button>
<button
disabled = {this.state.shoppingList.length === index + 1}
onClick = { () => this._handleItemSort("down", index) } >DOWN</button>
</div>
</li>)
)}
</ol>
</div>
);
}
}
Ваша функция arraymove ничего не возвращает, поэтому this.setState({shoppingList: arraymove(shoppingList, currentIndex , currentIndex - 1) }) эквивалентен this.setState({shoppingList: undefined}). Я уверен, что это не то, что вам нужно.
Спасибо за ваш комментарий, я попытался добавить такой возврат: return arr.splice(toIndex, 0, element);, но ошибка все еще существует



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


arraymove не возвращается, он изменяет состояние списка и возвращает undefined.
Итак, звонок
shoppingList: arraymove(shoppingList, currentIndex , currentIndex - 1)
эквивалентно
shoppingList: undefined
Так что исправление минимальное:
const shoppingList = [...this.state.shoppingList];
arraymove(shoppingList , currentIndex , currentIndex - 1)
this.setState({
shoppingList: shoppingList
})
Спасибо, что указали на это. Итак, я попробовал следующее: `function arraymove (arr, fromIndex, toIndex) {var element = arr [fromIndex]; arr.splice (fromIndex, 1); вернуть arr.splice (toIndex, 0, element); } `и ошибка такая же
Вы можете изменять массив на месте, просто попробуйте обновленный пример!
Возврат arr.splice() даст вам массив, содержащий удаленные элементы. Если удален только один элемент, возвращается массив из одного элемента. Если элементы не удалены, возвращается пустой массив.
Вам нужно вернуть модифицированный массив следующим образом:
function arraymove(arr, fromIndex, toIndex) {
var element = arr[fromIndex];
arr.splice(fromIndex, 1);
arr.splice(toIndex, 0, element);
return arr;
}
Спасибо! Так глупо с моей стороны не использовать модифицированный массив. Отмечу твой ответ через 5 минут
arraymove ничего не возвращает, добавьте возврат в конец вашей функции
arraymoveсreturn arr