javascript - 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.
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! :)
解决方案
我尝试运行您的应用程序,但没有成功。因此,下面的代码假设其他所有内容都已设置并在您的应用程序中正常工作。
不要使用类装饰器@
,而是尝试直接连接到类(另外,我强烈建议清理你的代码,这真的很难阅读)。
几个注意事项:
- 为您的所有函数使用更好的声明性名称(
this.update()
--update WHAT!?!? 虽然这对您来说很有意义,但对于从未见过您的应用程序的开发人员来说,他们会问同样的问题) - 按照推荐的方式设置redux reducer switch/case。
- 将相似的 redux 状态组合成一个 reducer。例如,您有
image
和images
。有什么不同?如果一个是用于索引的数字,另一个是用于图像的数组,那没关系,您仍然可以使用单个 reducer(如下所示)。 - 创建一个
actions
文件夹来处理 Redux 操作和一个types
用于 Redux 类型的文件夹 - 将redux-thunk用于异步函数(如
fetch
) - 创建一个单独的
Upload Images
表格。不要将它与您的Images
组件混为一谈。 - 你实际上不需要 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)
推荐阅读
- r - 使用 httr 连接到特定的 IP 地址
- c# - ASP.NET MVC:将查询数据传输到控制器中的模型类对象
- javascript - 如何操作 Dom 只选择标签内的文本内容?
- vb.net - AppendAllText 不会将 textbox1.text 中的新行保存到 .txt 文件中
- python - 两个 2 秩张量的 TensorFlow 外积
- java - 电话号码到java中多个数字的单词的功能
- rest - 格式化日期以响应 POST REST API
- c# - 如何在我们单击游戏对象的同一位置实例化粒子系统?
- c# - StackExchange.Redis.RedisConnectionException:无法连接到 redis 服务器;连接超时
- html - 如果父级兄弟的子级具有指定类,则 CSS 设置元素样式