Я пытался запустить ваше приложение, но оно не сработало.Таким образом, код ниже предполагает, что все остальное настроено и работает должным образом в вашем приложении.
Вместо того, чтобы использовать декоратор класса @
, попробуйте подключиться напрямую к классу (также я очень рекомендую очистить ваш код, это действительно трудно читать).
Несколько заметок:
- Используйте лучшие декларативные имена для всех ваших функций (
this.update()
- обновите ЧТО!?!? Хотя это имеет смысл для вас, для разработчика, который никогда не видел ваше приложение, они 'задам тот же вопрос) - Следуйте рекомендованному способу установки переключателя / корпуса редуктора-редуктора .
- Объедините аналогичное состояние редуктора в один редуктор.Например, у вас есть
image
и images
.Какая разница?Если одно - это число для индексации, а другое - массив для изображений, это нормально, вы все равно можете использовать один редуктор (как показано ниже). - Создайте папку
actions
для обработки действий Redux иПапка types
для типов Redux - Используйте redux-thunk для асинхронных функций (например,
fetch
) - Создайте отдельную форму
Upload Images
.Не смешивайте это с вашим Images
компонентом. - Вам на самом деле здесь не нужен Redux (если вы не делитесь им с другими вложенными компонентами).Вы можете просто использовать React для локальных
state
.
types / index.js (типы редукционных действий)
export const UPDATE_IMAGE_INDEX = "UPDATE_IMAGE_INDEX";
export const UPDATE_IMAGES = "UPDATE_IMAGES";
редукторы / 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 (создатели избыточных действий)
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!'} }));
)
компоненты / контент / профиль / 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)