#javascript #reactjs #react-hooks #use-effect #use-state
#язык JavaScript #реагирует на #реагируют-крючки #эффект использования #состояние использования
Вопрос:
Объект, который я хочу отредактировать, редактируется в формате JSON, но в браузере отображаются только предыдущие данные. Я использую эти крючки, чтобы получить список продуктов из локального хранилища
const Cart = () =gt; { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); useEffect(()=gt;{ setProducts(loadCart()); setLoading(false) },[])
Затем я сопоставляю все объекты
const mapProducts = (products) =gt; { return ( lt;gt; {products.map((product) =gt; { return ( lt;gt; lt;div className="cart-detail"gt; lt;h4gt;{product.name} - {product.price}$ / total: {product.price * product.amount}$lt;/h4gt; lt;h4gt;{product.amount}lt;/h4gt; lt;button onClick={() =gt; incrementAmount(product)}gt; lt;/buttongt; lt;/divgt; lt;/gt; ) })} lt;/gt; ) } return ( lt;Base title="Cart"gt; {loading amp;amp; lt;h1gt;Loading...lt;/h1gt;} {!loading amp;amp; mapProducts(products)} lt;/Basegt; )
incrementAmount()
функция выглядит так:
const incrementAmount = (product) =gt; { let tempList = products for (let i = 0; i lt; tempList.length; i ) { if (tempList[i].id === product.id) { tempList[i].amount ; } } setProducts(tempList) }
Судя по тому, что я вижу в консоли, массив выглядит нормально, и объект, который я хотел отредактировать, был отредактирован. Фе: у меня был объект {имя:»капюшоном», размер:3} после нажатия на кнопку » » изменяется правильно в {название:»капюшоном», размер:4} (как products
и tempList
), но только в консоли, в документе, он все равно отображается product.amount
как 3, и я понятия не имею, почему
Комментарии:
1. Вам нужно создать новый экземпляр массива
let tempList = [...products]
и использовать его для установки нового состояния.
Ответ №1:
Вместо передачи объекта setState
вы можете передать функцию, и когда у вас есть объект в состоянии, в котором вы хотите сохранить старые значения, вы должны использовать функцию.
Поскольку state
они могут обновляться асинхронно, вам не следует полагаться на их значения для вычисления следующего состояния.
Вы должны изменить incrementAmount()
функцию следующим образом:
const incrementAmount = (product) =gt; { setProducts(prevState =gt; { const newState = [...prevState]; for (let i = 0; i lt; newState.length; i ) { if (newState[i].id === product.id) { newState[i].amount ; } } return newState; }); }
Ответ №2:
Это связано с тем, что react запускает повторную отправку только при изменении состояния. Когда вы вызываете setProducts
incrementAmount
, вы, по сути, передаете один и тот же объект (с одним обновленным вложенным свойством). Поэтому react не регистрирует это как изменение состояния. Это связано с тем, как объекты и массивы работают в Javascript. Чтобы ваш код работал, измените let tempList = products
его на let tempList = [...products]
. Это создаст новый объект в памяти и скопирует из него значения products
. И , наконец, когда вы передадите это setProducts
, будет запущен повторный запрос на обновление вашего HTML.