#javascript #reactjs #context-api #use-reducer #actiondispatch
#javascript #reactjs #реагировать-контекст #использовать-reducer #actiondispatch — распределение действий
Вопрос:
Я довольно новичок в использовании контекстного API и перехватов в react. я столкнулся с проблемой, заключающейся в том, что начальное состояние не обновляется при попытке передать отправку действия с использованием ссылки на useReducer
, хотя объекты передаются ему. Код выглядит следующим образом:reducer.js
export const initialState={
basket:[ ],
}
const reducer= (state= initialState, action) => {
console.log(action);
switch(action.type) {
case 'ADD_TO_BASKET':
return {
...state,
basket:[...state.basket,action.item]
};
case 'REMOVE_FROM_BASKET':
//we cloned the basket
let newBasket = [...state.basket];
const index= state.basket.findIndex((basketItem) => basketItem.id === action.id);
if (index >= 0) {
//item exist in basket , remove it
newBasket.splice(index, 1);
} else {
console.warn (
'cant remove product (id: ${action.id}) as its not in basket'
);
}
return {...state, basket: newBasket,};
break;
default:
return state;
}
}
export default reducer;
console.log(action)
в приведенном выше примере указано item: {…} id: "101" image: "https://images.pexels.com/photos/534/animal-countryside-agriculture-farm.jpg" price: 11.96 rating: 5 title: "dress1" <prototype>: Object { … } type: "ADD_TO_BASKET" <prototype>: Object { … }
, что объект передается в редуктор, но начальное состояние не обновляется. не работает только случай: ADD_TO_BASKET, другой случай: REMOVE_FORM_BASKET работает нормально.Я был бы очень признателен, если кто-нибудь сможет мне помочь.
вот другие файлы для ссылки. stateProvider.js
//we need this to track the basket
//setup data layer
import React, { createContext , useContext, useReducer } from "react";
import reducer, {initialState} from './reducer';
//this is the data Layer
export const StateContext = createContext();
//BUILD a provider
export const StateProvider = ({children}) =>{
const state = useReducer(reducer, initialState);
return (
<StateContext.Provider value={state}>
{children}
</StateContext.Provider>
);
}
//this is how we use it inside of a component
export const useStateValue = () =>useContext(StateContext);
product.js
import { useStateValue } from './StateProvider';
import "./product.css";
function Product ({id,title,image,price,rating}){
const [{}, dispatch] = useStateValue();
const addToBasket =() => {
console.log("am clicked");
dispatch({
type: 'ADD_TO_BASKET',
item: {
id: id,
title: title,
image: image,
price: price,
rating: rating
},
});
};
return (......
......
.....
header.js
import "./Header.css";
import {Link} from "react-router-dom"
import { useStateValue } from './StateProvider';
function Header() {
//const [state,dispach] = useStateValue();
const [{basket,user}] = useStateValue();
console.log(basket);
return(
<div>
.
.
.
<Link to="/checkout" className="header_link">
<div className="header_optionbasket">
<ShoppingBasketIcon/>
<span className="header_optiontwo basketcount">{basket.length}</span>
</div>
</Link>
.
.
.
</div>
)
после того, как будет обновлено начальное состояние корзины.длина в header.js было предложено обновить, но оно остается 0, но если я жестко закодирую объект в initialState>basket, то корзина.длина обновляется. но объекты не добавляются в initialState > корзина
Ответ №1:
export const initialState={
basket:[ ],
}
const reducer= (state=initialState, action) => {
console.log(action);
switch(action.type) {
case 'ADD_TO_BASKET':
return {
...state,
basket:[...state.basket,action.item]
};
Вы должны инициализировать состояние в reducer. Также вам не нужно добавлять операторы Break в reducer.
Комментарии:
1. спасибо за твою помощь, брат, я реализовал и то, и другое, что ты сказал в коде, но начальное состояние все еще не обновляется
2. Вот codesandbox для вас. r1mkp.csb.app . P.S (Для удаления логики требуется некоторый рефакторинг, который усложняет использование метода JS reduce или filter.)