React Redux-带有互斥选项的选择下拉列表

时间:2018-11-21 22:28:44

标签: reactjs react-redux

我正在为此抓挠头。而且我发现这也不容易解释。我会尽力的:

我有一个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: {}
      })
    )
}

节点表达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
  }
}

1 个答案:

答案 0 :(得分:0)

因此,我设法通过重组并完全摆脱了ProjectGridPosition模型来使其工作。这样做使整个过程变得更加简单。然后,我完全重写了路线:

router.post(
  '/set_grid_position',
  passport.authenticate('jwt', { session: false }),
  async (req, res) => {
    let project = await getProjectById(req.body.projectId)
    const query = {
      'images.gridPosition': req.body.position
    }
    let formerRankProject = await getProjectByQuery(query)

    project = await updateRank(project, req.body.imageId, req.body.position)

    if (formerRankProject !== null) {
      formerRankProject = await UpdateIfDifferentProject(
        formerRankProject,
        project._id,
        req.body
      )
      formerRankProject.save()
    }

    project
      .save()
      .then(project => res.json(project))
      .catch(err => res.json(err))
  }
)

现在可以使用了。我不完全知道问题出在哪里,但是正如@Tex在评论中指出的那样,我有很多层次的嵌套-因此可能肯定会出问题。

我将其标记为正确的答案-尽管这可以解决,但人们知道,我仍在寻求帮助。