React / Redux не обновляет состояние должным образом и не может использоваться в компоненте - PullRequest
0 голосов
/ 14 января 2020

Я новичок в React и Redux и следую официальному примеру Todo List из документации Redux https://redux.js.org/basics/example и недавно изменил свой код в соответствии со структурой компонентов представления / контейнера. Я пробовал много разных способов перемещения вызова 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'
}

уменьшители / веса. js

const initialState = {weights: []}

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

компоненты / элементы / индекс. 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)

компоненты / элементы / 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

компоненты / элементы / 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;

В настоящее время я вызываю API в компоненте компонентов / элементов / индекса. js путем импорта соответствующего Диспетчерское действие и использование connect (), однако вместо того, чтобы делать это и передавать веса, мне нужно иметь возможность вызывать API где-то еще и визуализировать компонент VisibleWeights на основе фильтра, выбранного из другого компонента (я не отображается, так как он работает правильно и обновляет состояние p в некоторых случаях, но может определенно добавить, если это необходимо показать в контексте. Комментарии. Последние два дня я работаю над тем, чтобы сделать эту мелочь правильной, и не могу понять, что нужно изменить, чтобы сделать эту работу должным образом. Я знаю, что API вызывается правильно, но не знаю, как нужно менять компоненты, чтобы правильно его отображать. ** Когда я пытаюсь вызвать компонент вместо компонента, я получаю сообщение об ошибке: «TypeError: Невозможно прочитать свойство« map »из неопределенного» **

1 Ответ

0 голосов
/ 14 января 2020

Поскольку вы объявляете weights как пустой массив [] в исходном состоянии в reducers/weights.js

И вы его деструктурируете, как показано ниже

const { weights } = this.props.weights;

в качестве весов как согласно вашему объявлению undefined вы получаете ошибку

TypeError: Cannot read property 'map' of undefined

, поэтому попробуйте изменить ее в соответствии с вашими точными требованиями

Убедитесь, что весь ваш код работает даже без данных, потому что все Компонент отрисовывается перед вызовом API, поэтому либо обработайте компоненты для рендеринга с пустыми данными, и убедитесь, что ваш код не обрабатывается до получения данных API

В соответствии с вашим кодом, он считает wights массивом объектов поэтому внесение следующих изменений не повредит вашему приложению, я думаю

File : components/Items/index.js

In render Функция изменит следующую строку

const { weights } = this.props.weights;

до

const { weights = [] } = this.props;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...