我有使用 axios 的带有 Redux 的 React-App。我在
fetchById
组件中使用了 courseDetails.jsx
操作,但状态并未用新值更新。由于使用 fetchById
从后端获取值需要一些时间,因此由于先前组件(课程)的旧状态,组件显示错误。redux-logger
显示下一个状态的正确值,但组件未更新新状态。
这是 courseDetails.jsx
组件代码。
import React, { useState, useEffect } from "react";
import {useDispatch,useSelector} from 'react-redux';
import { Link,useParams,useHistory } from 'react-router-dom';
import * as actions from "../_actions/courseActions";
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import parse from 'html-react-parser';
const useStyles = makeStyles({
title: {
fontSize: 14,
display: 'flex',
},
pos: {
marginBottom: 12,
},
card: {
padding:10,
marginTop:10,
display: 'flex',
flex:1,
},
cardAction: {
display: 'block',
textAlign: 'initial'
},
cardMedia: {
width: 160,
},
});
export default function CourseDetails(props) {
const [loading, setLoading] = useState(true);
const classes = useStyles();
let {courseId}=useParams();
let {courseTitle}=useParams();
let history = useHistory()
const dispatch = useDispatch();
useEffect(() => {
//call the action creator with dispatch
// and wait until the promise resolves
actions.fetchById(courseId)(dispatch)
setLoading(false);
}, []);
let single= useSelector(state=>state.course.list)
//const course=myList.filter(x=>x.courseId==courseId);
console.log("course in courseDetails",single)
return (
<div>
{loading === true ? (<em>Loading!please wait...</em>) : (
<Card className={classes.card} variant="outlined">
<CardContent>
<Typography variant="h5" component="h2">
{single.courseTitle}
</Typography>
<Typography variant="h5" component="h2">
{single.subject}
</Typography>
<Typography className={classes.title} color="textSecondary" gutterBottom>
Fee: {single.fee}
</Typography>
<Typography variant="body2" component="p">
{parse(single.details)}
<br/>
updated on: {single.updatedOn}
</Typography>
<Typography variant="subtitle1" color="primary">
<div><br/>
<Link to={`/CourseLessons/${courseId}`}
><Button size="small" variant="contained" color="secondary"> Free Lectures </Button> </Link>-----
</div>
</Typography>
</CardContent>
</Card>
)}
</div>
);
}
旧状态显示
lessons.jsx
组件中的课程列表。
尝试渲染 CourseDetails.jsx
组件并希望在 let single= useSelector(state=>state.course.list)
行中显示单个课程,由于旧状态下的 lessons
值,它会生成错误。
这是coursActions.js
的代码
export const fetchById = (id) => dispatch => {
courseApi.course().fetchById(id)
.then(response => {
dispatch({
type: ACTION_TYPES.FETCH_BY_ID,
payload: response.data
})
})
.catch(err => console.log(err))
}
这是
coursApi.js
代码
import axios from "axios";
import config from 'config';
const baseUrl = `${config.apiUrl}/api/`
export default {
course(url = baseUrl + `Courses/`) {
return {
fetchAll: () => axios.get(url),
fetchById: id => axios.get(url + id),
create: newRecord => axios.post(url, newRecord),
update: (id, updateRecord) => axios.put(url + id, updateRecord),
delete: id => axios.delete(url + id)
}
}
}
这是
courseReducer.js
代码。
import { ACTION_TYPES } from '../_constants';
const initialState = {
list: []
}
export const course=(state = initialState, action)=>{
switch (action.type) {
case ACTION_TYPES.FETCH_ALL:
return {
...state,
list: [...action.payload]
}
case ACTION_TYPES.FETCH_BY_ID:
return {
...state,
list: [action.payload]
}
case ACTION_TYPES.CREATE:
return {
...state,
list: [...state.list, action.payload]
}
default:
return state
}
}
这里是rootReducer中的combinedReducer
import { combineReducers } from 'redux';
import { authentication } from './authentication.reducer';
import { registration } from './registration.reducer';
import { users } from './users.reducer';
import {course} from '../_reducers/courseReducer';
import {lesson} from '../_reducers/lessonReducer';
import {student} from '../_reducers/studentReducer';
import {tutor} from '../_reducers/tutorReducer';
import {need} from '../_reducers/needReducer';
import {post} from '../_reducers/postReducer';
import { alert } from './alert.reducer';
export const rootReducer = combineReducers({
authentication,
registration,
users,
course,
post,
need,
lesson,
student,
tutor,
alert
})
export default rootReducer;
这是
store
代码
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
import {rootReducer} from '../_reducers';
const loggerMiddleware = createLogger();
export const store = createStore(
rootReducer,
applyMiddleware(
thunkMiddleware,
loggerMiddleware
)
//window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
这可能对任何人都有帮助。但可能是比我分享的更好的解决方法。我在
setTimeout()
中使用了fetchById
,根据需要更新了状态并解决了我的问题..完整的useEffect
如下:courseDetails.jsx