简体   繁体   中英

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.

数组截图

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:

  • components/Content/Profile/Images.js
  • components/Content/User.js
  • store/image.js
  • store/images.js

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

maybe you should use the componentWillReceiveProps in the Component life cycle

see react docs --> here

or just use pureComponents (functions nether classes)

pureComponents updates on props by default

I tried running your app, but it didn't work. So the code below is assuming that everything else is set up and working properly in your app.

Instead of using the class decorator @ , try connecting directly to the class (also, I'd highly recommend cleaning up your code, it's really hard to read).

Several notes:

  1. Use better declarative names for all of your functions ( this.update() -- update WHAT!?!? While it makes sense to you, to a developer who has never seen your app, they'll ask the same question)
  2. Follow the recommended way to setup a redux reducer switch/case .
  3. Combine similar redux state into one reducer. For example, you have image and images . What's the difference? If one is a number for indexing and the other is an array for images, that's okay, you can still use a single reducer (as shown below).
  4. Create an actions folder to handle Redux actions and a types folder for Redux types
  5. Use redux-thunk for async functions (like fetch )
  6. Create a separate Upload Images form. Don't lump it with your Images component.
  7. You actually don't need Redux here (unless you're sharing it with other nested components). You can just use React's local state .

types/index.js (redux action types)

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

reducers/imagesReducer.js (structure your switch/case s like so)

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 action creators)

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 (displays images -- nothing else; also, allows you to view them one by one via buttons)

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM