React/Redux 状态更新不正确,无法在组件中使用

React/Redux Doesn't Update State Properly and Can't Be Used in Component

我是 React 和 Redux 的新手,一直在关注官方 Redux 文档待办事项列表示例 https://redux.js.org/basics/example,最近更改了我的代码以遵循 presentational/container 组件结构。我已经尝试了许多不同的方法来移动 API 调用,但是状态中的权重对象经常显示为未定义(可能是因为它试图在实际 API 调用之前被使用,但是我不知道如何从现在的位置更改 API 调用。

文件如下:

actions/index.js

import axios from 'axios';

export const getWeights = () => dispatch => {
  axios.get('/api/weights')
  .then(res => 
    dispatch({
      type: 'GET_WEIGHTS',
      payload: res.data
    })
  )
}

export const setShownCategory = category => ({
  type: 'SET_SHOWN_CATEGORY',
  category
})

export const Categories = {
  SHOW_ALL: 'SHOW_ALL',
  SHOW_ACCESSORIES: 'SHOW_ACCESSORIES',
  SHOW_BARBELLS: 'SHOW_BARBELLS',
  SHOW_DUMBBELLS: 'SHOW_DUMBBELLS',
  SHOW_PLATES: 'SHOW_PLATES',
  SHOW_RACKS: 'SHOW_RACKS',
  SHOW_OTHER: 'SHOW_OTHER'
}

reducers/weights.js

const initialState = {weights: []}

export default function(state = initialState, action) {
  switch (action.type) {
    case 'GET_WEIGHTS':
      return {
        ...state,
        weights: action.payload
      }
    default:
      return state;
  }
}

components/Items/index.js

import React from 'react';
import CategoryBar from './CategoryBar'

import Typography from '@material-ui/core/Typography';
import { connect } from 'react-redux';
import { getWeights } from '../../actions'
import WeightItems from './WeightItems';

class Items extends React.Component {
  componentDidMount() {
    console.log(this.props)
    this.props.getWeights();
  }

  render() {
    const { weights } = this.props.weights;
    return (
      <div>
         <Typography variant="h4">Browse</Typography>
         <div>
           <CategoryBar />
         </div>
         <WeightItems weights={weights} />
       </div>
    )
  }
}

const mapStateToProps = state => ({
  weights: state.weights
});

export default connect(
  mapStateToProps,
  { getWeights }
)(Items)

components/Items/WeightItems.js

import React from 'react'

import Grid from '@material-ui/core/Grid';
import { makeStyles } from '@material-ui/core/styles';
import Item from './Item'

const useStyles = makeStyles({
  items: {
    display: 'flex',
    margin: 'auto',
  }
})

const WeightItems = ({ weights }) => {
  const classes = useStyles()

  return (
    <Grid className={classes.items} container direction="row" justify="center" alignItems="center" spacing={3}>
      {weights.map(weight => <Item key={weight.id} weight={weight} />)}
    </Grid>
  )
}

export default WeightItems

components/Items/Item.js

import React from 'react';
import Paper from '@material-ui/core/Paper';
import Grid from '@material-ui/core/Grid';

const Item = ({ weight }) => {
  return (
    <Grid item xs={12} sm={6} md={4}>
      <Paper>{weight.title}</Paper>
    </Grid>
  )
}

export default Item

store.js

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const initialState = {};

const middleWare = [thunk];

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  rootReducer,
  initialState,
  composeEnhancers(applyMiddleware(...middleWare))
);

export default store;

目前,我通过导入相应的调度操作并使用 connect() 来调用 components/Items/index.js 组件中的 API,但是,我没有这样做并传递权重,而是需要能够在其他地方调用 API 并根据从不同组件中选择的过滤器呈现 VisibleWeights 组件(我没有显示它正常工作并正确更新状态,但绝对可以添加如果它需要显示上下文)。

containers/VisibleWeights.js

import { connect } from 'react-redux'
import { Categories } from '../actions'
import WeightItems from '../components/Items/WeightItems'

const getVisibleWeights = (weights, category) => {
  console.log(weights, category)
  switch(category) {
    case Categories.SHOW_ACCESSORIES:
      return weights.filter(weight => weight.category === 'Accessories')
    case Categories.SHOW_BARBELLS:
      return weights.filter(weight => weight.category === 'Barbells')
    case Categories.SHOW_DUMBBELLS:
      return weights.filter(weight => weight.category === 'Dumbbells')
    case Categories.SHOW_PLATES:
      return weights.filter(weight => weight.category === 'Plates')
    case Categories.SHOW_RACKS:
      return weights.filter(weight => weight.category === 'Racks')
    case Categories.SHOW_OTHER:
      return weights.filter(weight => weight.category === 'Other')
  }
}

const mapStateToProps = state => ({
  weights: getVisibleWeights(state.weights, state.shownCategory)
})

export default connect(
  mapStateToProps,
)(WeightItems)

如果我可以添加任何其他代码或评论,请告诉我。在过去的两天里,我一直在努力让这件小事变得正确,但无法弄清楚需要改变什么才能使它正常工作。我知道 API 被正确调用,但不知道如何更改组件才能正确显示它。 **当我尝试调用组件而不是组件时,出现错误:'TypeError: Cannot read 属性 'map' of undefined' **

正如您在 reducers/weights.js

中将 weights 声明为处于初始状态的空数组 []

你正在解构它,如下所示

const { weights } = this.props.weights;

因为您声明的权重是 undefined 您收到错误

TypeError: Cannot read property 'map' of undefined

所以尝试根据您的具体要求进行更改

确保您的所有代码即使在没有数据的情况下也能正常工作,因为整个组件在 API 调用之前渲染,因此要么处理组件以使用空数据渲染并确保您的代码不会在您之前 beak获取 API 数据

根据您的代码,它认为 wights 是对象数组,因此进行以下更改不会破坏您的应用程序,我认为

文件: components/Items/index.js

render 函数中更改以下行

const { weights } = this.props.weights;

const { weights = [] } = this.props;