react-redux 状态未使用 fetchById 操作在组件中更新为新状态,但 redux-logger 显示正确的新状态

问题描述 投票:0回答:1

我有使用 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__()

);
reactjs react-redux
1个回答
0
投票

这可能对任何人都有帮助。但可能是比我分享的更好的解决方法。我在

setTimeout() 
中使用了
fetchById 
,根据需要更新了状态并解决了我的问题..完整的
useEffect
如下:
courseDetails.jsx

© www.soinside.com 2019 - 2024. All rights reserved.