首页 > 解决方案 > React Component props won't update

问题描述

this.props.images is not properly updating when I dispatch the array of images. The array just displays as empty, though the resulting array is not.

screenshot of arrays

I've linked my repo for the project and listed the files that need to be referenced.

React Web App Repo

Furbabies Co Web App

The files that you need to look at are as follows:

If you want to help with this project by contributing that'd be great! :)

标签: javascriptreactjsreduxreact-reduxreact-props

解决方案


我尝试运行您的应用程序,但没有成功。因此,下面的代码假设其他所有内容都已设置并在您的应用程序中正常工作。

不要使用类装饰器@,而是尝试直接连接到类(另外,我强烈建议清理你的代码,这真的很难阅读)。

几个注意事项:

  1. 为您的所有函数使用更好的声明性名称(this.update()--update WHAT!?!? 虽然这对您来说很有意义,但对于从未见过您的应用程序的开发人员来说,他们会问同样的问题)
  2. 按照推荐的方式设置redux reducer switch/case
  3. 将相似的 redux 状态组合成一个 reducer。例如,您有imageimages。有什么不同?如果一个是用于索引的数字,另一个是用于图像的数组,那没关系,您仍然可以使用单个 reducer(如下所示)。
  4. 创建一个actions文件夹来处理 Redux 操作和一个types用于 Redux 类型的文件夹
  5. redux-thunk用于异步函数(如fetch
  6. 创建一个单独的Upload Images表格。不要将它与您的Images组件混为一谈。
  7. 你实际上不需要 Redux (除非你与其他嵌套组件共享它)。你可以只使用 React 的 local state

types/index.js (redux 动作类型)

export const UPDATE_IMAGE_INDEX = "UPDATE_IMAGE_INDEX";
export const UPDATE_IMAGES = "UPDATE_IMAGES";

reducers/imagesReducer.js(像这样构造你switch/case的 s)

const initialState = {
   index: 0,
   data: []
}

const imagesReducer = (state=initialState, { type, payload }) => { //es6 destructing -- type=action.type, payload=action.payload
  switch (type) {
    case 'UPDATE_IMAGE_INDEX':
      return { ...state, index: payload } // accessible via state.images.index
    case 'UDPATE_IMAGES':
      return {...state, data: payload } // accessible via state.images.data
    default:
      return state
  }
};

export default imagesReducer;

actions/imageActions(redux 动作创建者)

import * as types from '../types';

// the following is a Redux thunk action (thunk handles returned async functions -- you have to install it and add it as middleware)
export const fetchImages = (id, type) => dispatch => (
  fetch(`/images/${type}/${id}`) // fetch images
    .then(res => res.json()) // turn result into JSON
    .then(({ result }) => dispatch({ type: types.UPDATE_IMAGES, payload: result })) // send result to `imagesReducer`
    .catch(() => console.log('Network error...'));
)

// this updates the image index
export const updateImageIndex = payload => dispatch => (
  dispatch({ type: types.UPDATE_IMAGE_INDEX, payload })
)

// this should upload an image, save it, then return all current images
export const uploadImage = (type, id, data) => dispatch => (
   fetch(`/images/${type}/${id}`, {
      method: 'POST',
      body: data
     }
   )
   .then(res => res.json())
   .then(({ result }) => dispatch({ type: types.UPDATE_IMAGES, payload: result }))
   .catch(() => dispatch({ type: 'UPDATE_ERROR', payload: { message: 'Network error...try again later!'} }));
)

components/Content/Profile/ShowImages.js(显示图像——仅此而已;另外,允许您通过按钮一一查看)

import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import { fetchImages, updateImageIndex } from '../../../actions/imageActions';

class ShowImages extends PureComponent {   
  componentDidMount = () => {
    inputs.lazyload(`/css/images.min.css`).catch(() => console.log('Network error...'));
    this.props.fetchImages(this.props.type, this.props.id); // fetches images via redux action creator shown above
  }

  handlePrevClick = e => {
    const { index, images } = this.props;
    if (index-1 <== images.length) {
       this.props.updateImageIndex(index-1); // reduces redux image index by 1 via redux action creator shown above
    }
  }

  handleNextClick = () => {
    const { index, images } = this.props;   
    if (index+1 <== images.length) {
       this.props.updateImageIndex(index+1); // increases redux image index by 1 via redux action creator shown above
    }
  }

  // ideally this should be done BEFORE being sent to the front-end, as is, every time this.props.index is updated, this has resort them -- ruins client-side performance and wastes resources.
  sortImages = () => {
   return this.props.images.sort((a, b) => {
      if (a.isDefault && b.isDefault) return a.src.localeCompare(b.src);
      return a.isDefault || b.isDefault;
    });
  }


  render = () => {
    const { index, images } = this.props;
    const sortedImages = this.sortImages();
    const prev = images.length && index > 0 ? '<' : '+';
    const next = images.length && index < images.length ? '>' : '+';

    return (
      <div className='images'>
        <button className='prev' onClick={this.handlePrevClick}>
          {prev}
        </button>
        <img src={sortedImages[index]} />
        <button className='next' onClick={this.handleNextClick}>
          {next}
        </button>
      </div>
    );
  }
}

const mapStateToProps = state => ({
   images: state.images.data,
   index: state.images.index,
   user: state.user,
   type: store.current.type
})

const mapDispatchToProps = dispatch => ({ fetchImages, updateImageIndex }); 


export default connect(mapStateToProps, mapDispatchToProps)(ShowImages)

推荐阅读