Я почесал голову на этом.И я считаю, что это также не легко объяснить.Я приложу все усилия:
У меня есть HTML-таблица, в каждой строке есть изображение и, среди других элементов, также выпадающий список с топ-10 списком, чтобы ранжировать изображение.Когда пользователь выбирает ранжирование, база данных соответствующим образом обновляется -> Рейтинг 10 текущего изображения сохраняется в записи изображения, а ранг предыдущего изображения для наследования позиции обновляется до «ноль».(это уже работает -> так что, если я перезагружаю страницу, все получается нормально).Чего я не могу достичь, так это для обновленного массива изображений, который я получаю обратно из БД, для обновления состояния (или реквизита) и, следовательно, для выбранного значения параметра изображения, которое ранее унаследовало ранг.Вот мой ImageList
Компонент (важные части):
class ImageList extends Component {
constructor(props) {
super(props)
this.state = {
project: [],
description: '',
name: '',
values: [],
value: '',
positions: props.positions
}
}
updatePosition = (projectId, projectName, imageId, imgName, i, e) => {
this.props.setGridPosition(
projectId,
projectName,
imageId,
imgName,
e.target.value
)
}
getAllImages() {
let imageList = []
if (this.props.project.project) {
const { project, waiting } = this.props.project
for (let [i, img] of project.images.entries()) {
if (!img.isDeleted) {
let options = ['-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
this.props.positions[i] = img.gridPosition
let imgSrc = `/public/${project._id}/${img.originalName}`
imageList.push(
<tr
key={img._id}
style={waiting ? { opacity: '.5' } : { opacity: '1' }}
>
<td>
<img src={imgSrc} alt="" style={{ width: '60px' }} />
</td>
<SelectFieldGroup
name={`placeInGrid_${i}`}
onChange={this.updatePosition.bind(
this,
project._id,
project.name,
img._id,
img.originalName,
i
)}
options={options}
value={this.props.positions[i]}
/>
</td>
</tr>
)
}
}
}
return imageList
}
render() {
return (
<div className={styles['image-list']}>
<table className={styles['image-table']}>
<tbody>{this.getAllImages()}</tbody>
</table>
</div>
)
}
}
const mapStateToProps = state => ({
auth: state.auth,
project: state.project
})
export default connect(
mapStateToProps,
{ deleteImage, setGridPosition }
)(ImageList)
Я получаю реквизиты - проект и позиции (в виде пустого массива) - от родительского Компонента.
Я надеюсьвопрос как-то понятен.Я был бы очень признателен за любую помощь или указатели, где я ошибся.
Редактировать: В соответствии с просьбой, для пояснения, вот некоторые другие части кода:
SelectFieldGroup.js
:
import React from 'react'
import PropTypes from 'prop-types'
import cx from 'classnames'
import globalStyles from './Bootstrap.module.css'
import commonStyles from './Common.module.sass'
const SelectFieldGroup = ({ name, onChange, options, value, disabled }) => {
let optionArray = []
for (let [index, option] of options.entries()) {
optionArray.push(<option key={index}>{option}</option>)
}
return (
<div className={globalStyles['form-group']}>
<select
value={value}
className={cx(
globalStyles['custom-select'],
commonStyles['custom-select'],
commonStyles['dark-input']
)}
name={name}
onChange={onChange}
disabled={disabled}
>
{optionArray}
</select>
</div>
)
}
SelectFieldGroup.propTypes = {
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
disabled: PropTypes.string
}
export default SelectFieldGroup
Соответствующая часть imageActions.
:
export const setGridPosition = (
projectId,
projectName,
imageId,
imageName,
position
) => dispatch => {
dispatch(setWaiting())
const data = {
projectId: projectId,
projectName: projectName,
imageId: imageId,
imageName: imageName,
position: position
}
console.log(projectId)
axios
.post('/api/projects/set_grid_position', data)
.then(res => {
console.log(res.data)
dispatch({
type: SET_GRID_POSITION,
payload: res.data
})
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: {}
})
)
}
Узел Express API:
router.post(
'/set_grid_position',
passport.authenticate('jwt', { session: false }),
(req, res) => {
const errors = {}
Project.findById(req.body.projectId).then(currentProject => {
let updatedProject = currentProject
ProjectGridPosition.findOne({ position: req.body.position }).then(
gridPosition => {
if (req.body.position != '-') {
// Mark the previous position of the image as empty.
ProjectGridPosition.findOne({ imageId: req.body.imageId })
.then(oldPos => {
oldPos.isTaken = false
oldPos.save()
})
.catch(err => res.status(400).json(err))
// Set the gridPosition inside the image.
currentProject.images.forEach(img => {
if (img._id == req.body.imageId) {
img.gridPosition = req.body.position
}
})
currentProject.save(err => {
if (err) res.json(err)
else {
updatedProject = currentProject
}
})
if (gridPosition) {
if (gridPosition.projectId) {
Project.findById(gridPosition.projectId)
.then(project => {
console.log(project.name)
project.images.forEach(img => {
if (img.gridPosition == req.body.position) {
console.log(img.originalName)
img.gridPosition = '-'
}
})
project.save(err => {
if (err) {
res.json(err)
} else {
if (project == currentProject) {
updatedProject = currentProject
}
}
})
})
.catch(err => res.json(err))
}
gridPosition.projectId = req.body.projectId
gridPosition.projectName = req.body.projectName
gridPosition.imageId = req.body.imageId
gridPosition.imageName = req.body.imageName
gridPosition.isTaken = true
gridPosition.save()
res.json(updatedProject)
} else {
const newPosFields = {
projectId: req.body.projectId,
projectName: req.body.projectName,
imageId: req.body.imageId,
imageName: req.body.imageName,
position: req.body.position,
isTaken: true
}
new ProjectGridPosition(newPosFields)
.save()
.then(() => {
currentProject.save().then(() => {
res.json(currentProject)
})
})
.catch(err => res.json(err))
}
} else {
currentProject.images.forEach(img => {
if (img._id == req.body.imageId) {
img.gridPosition = req.body.position
}
})
currentProject.save(err => {
if (err) res.json(err)
ProjectGridPosition.findOne({ imageId: req.body.imageId }).then(
newPos => {
newPos.isTaken = false
newPos.save().then(() => {
currentProject.save().then(() => {
res.json(currentProject)
})
})
}
)
})
}
}
)
})
}
)
И, наконец, соответствующая частьprojectReducer.js
:
import {
// ...
SET_GRID_POSITION
} from '../actions/types'
const initialState = {
project: null,
projects: null,
loading: false,
waiting: false
}
export default function(state = initialState, action) {
switch (action.type) {
// ....
case SET_GRID_POSITION:
return {
...state,
project: action.payload,
waiting: false
}
default:
return state
}
}