我似乎真的在react和hook方面遇到了麻烦。我知道问题可能在于如何应对。我正在看一个教程,用5和我用6。我看了一下文件,但老实说,我找不到问题所在。它对我的主页有效,但现在产品页面不起作用了,老实说,我在过去找不到任何关于这个问题的答案。有人有主意吗??谢谢
import React, {useState, useEffect} from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Image, ListGroup, Button, Card } from 'react-bootstrap'
import Rating from '../components/Rating'
import Loader from '../components/Loader'
import Message from '../components/Message'
import { useParams } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { listProductDetails } from '../actions/productActions'
function ProductScreen({match}) {
const dispatch = useDispatch()
const productDetails = useSelector(state => state.productDetails)
const {loading, error, product} = productDetails
useEffect(() =>{
dispatch(listProductDetails(match.params.id))
},[])
ProductActions.js:
export const listProductDetails = (id) => async(dispatch) => {
try {
dispatch({type: PRODUCT_DETAILS_REQUEST})
const { id } = useParams();
const {data} = await axios.get(`/api/products/${id}`)
dispatch({
type: PRODUCT_DETAILS_SUCCESS,
payload: data
})
} catch (error) {
dispatch({
type: PRODUCT_DETAILS_FAIL,
payload: error.response && error.response.data.message
? error.response.data.message
: error.message,
})
}
}
productReducer.js:
export const productDetailsReducer = (state={product:{reviews:[]}},action) => {
switch(action.type){
case PRODUCT_DETAILS_REQUEST:
return {loading:true, ...state}
case PRODUCT_DETAILS_SUCCESS:
return {loading:false, product:action.payload}
case PRODUCT_DETAILS_FAIL:
return {loading:false, error: action.payload}
default:
return state
}
}
store.js:
import { legacy_createStore as createStore, combineReducers, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension'
import {productListReducer,productDetailsReducer} from './reducers/productReducers'
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
})
const initialState = {}
const middleware = [thunk]
const store = createStore(reducer, initialState,
composeWithDevTools(applyMiddleware(...middleware)))
export default store
export const listProductDetails = (id) => async(dispatch) => {
try {
dispatch({type: PRODUCT_DETAILS_REQUEST})
const { id } = useParams();
[...]
将id
作为listProductDetails
的参数传递,然后在函数中重新定义它。将const { id } = useParams();
移到ProductScreen
中,并将其作为参数传递给函数,而不是使用match
。
此外,listProductDetails
还返回一个以dispatch
为参数的异步函数。所以不要调用dispatch(listProductDetails(id))
,而是调用listProductDetails(id)(dispatch)
。
此外,在api中调用dispatch也不是一个好主意。您通常希望操作函数返回要在React组件中调度的内容。
function ProductScreen() {
const dispatch = useDispatch();
const { id } = useParams();
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect(() => {
const fetchData = async (id) => {
dispatch({ type: PRODUCT_DETAILS_REQUEST });
dispatch(await listProductDetails(id));
};
fetchData(id);
}, [dispatch, id]);
return <div>APP</div>;
}
In-ProductActions.js
export const listProductDetails = async (id) => {
try {
const { data } = await axios.get(`/api/products/${id}`);
return {
type: PRODUCT_DETAILS_SUCCESS,
payload: data,
};
} catch (error) {
return {
type: PRODUCT_DETAILS_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
};
}
};