我设置这个reducer.js文件以使用React的useReducer
https://reactjs.org/docs/hooks-reference.html#usereducer
import {useReducer} from 'react';
const initialState = {
test: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case 'reset':
return initialState;
case 'addTest':
return {test: state.test + 1};
case 'removeTest':
return {test: state.test - 1};
}
};
export const getReducer = () => {
return useReducer(reducer, initialState);
};
现在我可以通过getReducer
在不同的渲染函数中获取状态和调度:
import React from 'react';
import ReactDOM from 'react-dom';
import {getReducer} from './reducer';
const Button = (props) => (
<button
type="button"
onClick={() => props.dispatch({type: props.type})}>
{props.children}
</button>
);
const App = () => {
const [state, dispatch] = getReducer();
return (
<React.Fragment>
{state.test}
<Button dispatch={dispatch} type="addTest">Add 1</Button>
<Button dispatch={dispatch} type="removeTest">Remove 1</Button>
<Button dispatch={dispatch} type="reset">Reset</Button>
</React.Fragment>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
传递dispatch
函数并让其他组件调用props.dispatch确实感觉很奇怪。有没有更干净的方法来设置它?
如果你想尝试不同的模式,我会在这里设置回购:https://github.com/dancrew32/hooks
定义您的操作并将其映射到您的reducer怎么样?
const mapDispatch => dispatch => ({
reset: () => dispatch({ type: 'reset' }),
addTest: () => dispatch({ type: 'addTest' }),
removeTest: () => dispatch({ type: 'removeTest' })
})
const Button = (props) => (
<button
type="button"
onClick={props.onClick}>
{props.children}
</button>
);
const App = () => {
const [state, dispatch] = getReducer();
const actions = mapDispatch(dispatch)
return (
<React.Fragment>
{state.test}
<Button onClick={actions.addTest}>Add 1</Button>
<Button onClick={actions.removeTest}>Remove 1</Button>
<Button onClick={actions.reset}>Reset</Button>
</React.Fragment>
);
};
这里没有什么新鲜事;只是react-redux
做事方式的翻版。
import Swal from 'sweetalert2';
const userLists = JSON.parse(localStorage.getItem('user_data'));
export const loginUser = (dispatch, email, password) => {
const filtered = userLists.findIndex(obj => {
return obj.email === email;
});
if (
(email === userLists[filtered].email || email === "ari@arica.co") &&
(password === userLists[filtered].sandi || password === 12345)
) {
dispatch({
type: 'SUCCESS_LOGIN',
islogin: true,
});
Swal.fire({
icon: 'success',
title: 'Selamat',
text: 'Anda telah masuk',
footer: '<a href="">Selamat berbelanja</a>',
});
localStorage.setItem('nama', JSON.stringify(userLists[filtered].namaDepan));
localStorage.setItem('dataUser', JSON.stringify(userLists[filtered].email));
localStorage.setItem('islogin', JSON.stringify(true));
// console.log('ini user');
} else {
dispatch({
type: 'FAILED_LOGIN',
});
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'Something went wrong!',
footer: '<a href="">Why do I have this issue?</a>',
});
localStorage.setItem('islogin', JSON.stringify(false));
}
};
export const logOutUser = (dispatch, user) => {
console.log(user, 'ini user logout');
dispatch({
type: 'SUCCESS_LOGOUT',
});
localStorage.setItem('islogin', JSON.stringify(false));
localStorage.removeItem('nama');
};
export const addCart = (dispatch, payloadProduct) => {
console.log(dispatch, 'ini dispatch');
dispatch({
type: 'ADD_CART',
cart: payloadProduct,
quantity: 0,
});
};
export const addWish = (dispatch, payloadProduct) => {
console.log(dispatch, 'ini dispatch');
dispatch({
type: 'ADD_WISH',
cart: payloadProduct,
});
};
let islogin = localStorage.getItem('islogin')
? JSON.parse(localStorage.getItem('islogin'))
: false;
export const initialstate = {
islogin: false,
cart: [],
wish: [],
quantity: 0,
love: false,
};
export const AuthReducer = (initialstate, action) => {
switch (action.type) {
case 'SUCCESS_LOGIN':
return {
...initialstate,
user: action.email,
islogin: true,
};
case 'SUCCESS_LOGOUT':
return {
...initialstate,
islogin: false,
};
case 'ADD_CART':
return {
...initialstate,
cart: action.cart,
quantity: action.quantity++,
};
case 'ADD_WISH':
return {
...initialstate,
wish: action.cart,
};
default:
return { ...initialstate };
}
};
这是如何设置上下文缩减器的。
import { useState, useEffect } from 'react';
import axios from 'axios';
import { useContext, createContext } from 'react';
import { AuthReducer } from './Reducer';
import { initialstate } from './Reducer';
import { useReducer } from 'react';
export const ProductStateContext = createContext();
export const useProductState = () => {
return useContext(ProductStateContext);
};
export const ProductProvider = ({ children }) => {
const [items, setItems] = useState([]);
const [product, setProduct] = useState('');
const [detail, setDetail] = useState([]);
const [cart, dispatch] = useReducer(AuthReducer, initialstate);
const [qty, setQty] = useState(0);
const [dataCarts, setDataCarts] = useState();
const [isSearch, setIsSearch] = useState(false)
useEffect(() => {
axios.get('https://fakestoreapi.com/products').then(
response => {
setItems(response.data);
},
error => {
console.log(error);
}
);
}, []);
const searchUser = search => {
console.log(search, "ini value")
setProduct(
items.filter(item => {
return search.toLowerCase() === ''
? item
: item.title.toLowerCase().includes(search) ||
search.toLowerCase() === ''
? item
: item.category.toLowerCase().includes(search);
})
);
};
// Detail Produk
const detailProduct = item => {
setDetail(item);
};
// QUANTITY
let quantity = 0;
useEffect(() => {
if (cart.cart.length !== 0) {
cart.cart.map(item => {
quantity += item.quantity;
setQty(quantity);
});
} else {
setQty(0);
}
});
// TOTAL HARGA
const hitungTotalHarga = () => {
const totalHarga = cart.cart.reduce(
(acc, item) => acc + item.products.price * item.quantity,
0
);
return totalHarga.toFixed(2);
};
const cartValue = (item, index) => {
setDataCarts(item, index);
};
return (
<ProductStateContext.Provider
value={{
product,
searchUser,
items,
detailProduct,
detail,
cart,
dispatch,
qty,
hitungTotalHarga,
cartValue,
dataCarts,
setIsSearch,
isSearch
}}
>
{children}
</ProductStateContext.Provider>
);
};