复制redux状态到本地状态是否违背了redux哲学?

6
import React, { Component } from 'react'
import _ from 'lodash'
import { PageHeader, Row, Col, FormGroup, ControlLabel, Button, FormControl, Panel } from 'react-bootstrap'

import FieldGroup from '../fieldGroup/fieldGroup'
import PassagePreview from './preview'

class PassageDetail extends Component {
  constructor(props) {
    super(props)

    this.handleChange = this.handleChange.bind(this)

    this.state = {
      passageDetails: {}
    }

  }

  componentDidMount() {
    this.props.fetchPassage(this.props.params.passageId)
  }

  componentWillReceiveProps(nextProps) {
    if(nextProps.passageState.passageStatus === 'success') {
      this.setState({passageDetails: nextProps.passageState.passage})
    }
  }

  handleChange(e) {
    let passageDetails = this.state.passageDetails

    passageDetails[e.target.name] = e.target.value

    this.setState({passageDetails})
  }

  render() {
    if(this.props.passageState.passageStatus !== 'success') {
      return null
    }
    return (
      <div>
        <PageHeader>
          Create Passage
        </PageHeader>
        <Row>
          <Col md={6}>
            <FieldGroup
              type="text"
              label="Passage Title"
              name="title"
              onChange={this.handleChange}
              value={this.state.passageDetails.title}
            />

            <FieldGroup
              type="text"
              label="Passage Author"
            />
            <FormGroup>
              <ControlLabel>Passage Text</ControlLabel>
              <FormControl componentClass="textarea" placeholder="textarea" rows="20" />
            </FormGroup>
          </Col>
          <Col md={6}>
            <PassagePreview passageDetails={this.state.passageDetails} />
          </Col>
        </Row>

        <Row>
          <Col md={6} mdOffset={6}>
            <Button block bsStyle="primary">Create Passage</Button>
          </Col>
        </Row>
      </div>
    )
  }
}

export default PassageDetail

那是我的组件。容器是:
import { connect } from 'react-redux'
import * as PassagesActions from '../actions/passages'
import PassageMain from '../components/passage/main'

const mapStateToProps = (state) => {
  return {
    passageState: state.PassageReducer
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    fetchPassages: () => {
      const params = {
        url: `${process.env.REACT_APP_API_ENDPOINT}/passages`
      }
      dispatch(PassagesActions.fetchData(params, 'passages'))
    },
    fetchPassage: (passageId) => {
      const params = {
        url: `${process.env.REACT_APP_API_ENDPOINT}/passages/${passageId}`
      }
      dispatch(PassagesActions.fetchData(params, 'passage'))
    }
  }
}

export default connect(
  mapStateToProps, mapDispatchToProps
)(PassageMain)

所以你可以看到在我的componentDidMount中,我正在通过redux进行API调用,在componentWillReceiveProps中,我将其复制到本地状态。这样做的想法是,如果我对我的passage进行更改,它是在组件级别完成的,然后我可以通过一些尚未创建的redux操作将该对象传递回去。
这种方法在redux哲学中可行吗?我仍在努力理解redux,所以如果这个问题没有意义,请原谅。
3个回答

4
其他评论提出了一些好的观点,但也夸大了情况。根据Redux FAQ问题(http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state)

使用本地组件状态是可以的。作为开发人员,你的工作就是确定应用程序中哪些状态属于你的应用程序,并确定每个状态应该放在哪里。找到适合你的平衡点并坚持下去。

一些通常用于确定应将哪种数据放入Redux的规则:

  • 其他部分是否关心这些数据?
  • 您是否需要能够创建基于此原始数据的进一步派生数据?
  • 是否使用相同的数据来驱动多个组件?
  • 您是否希望能够将此状态恢复到特定时间点(即,时间旅行调试)?
  • 您是否想缓存数据(即,如果已经存在,则使用状态中的数据而不是重新请求它)?
因此,如果您希望在调度具有结果的操作之前使用本地组件状态作为“临时数据”区域,那么这是可以的。

3

出于好的原因,使用组件状态违背了“redux哲学”,你有一个用于存储和集中应用程序状态的架构和框架,你应该使用它!如果你使用组件状态,你就分散了应用程序状态,迟早会遇到灾难。尽可能坚持Redux架构,仅在处理次要UI细节时使用组件状态,或者更好的办法是根本不使用。

检查一下你的reducer可能会有所帮助,但如果你已经在Redux store中保存了passages的集合,那么显然你不需要使用组件状态。

如果你已经有了关于passage的基本信息,并且需要从服务器加载更多信息以供该组件使用,那么所有的passages都应该有一个标志,表示你是否已经拥有该信息,这样当你的组件加载时,只有在需要时才检索该信息。

没有必要使用componentWillReceiveProps,只需触发操作,在操作完成时在reducer中更新store,就可以了。你的集合将包含passage,你需要将其传递给组件(全部内容,而不仅仅是id)。

Redux是一个非常底层的框架,它给了你很大的自由度。如果你怀疑自己是否做出了正确的决定,始终记住:

  • 与应用程序相关的任何信息都会存储在Redux store中
  • 任何以任何方式影响应用程序的东西都是一个操作
  • React组件显示信息,并使用它们从用户那里收集到的信息触发redux操作,没有其他内容

另一个需要注意的事情是你的组件应该只接收它需要的属性。你正在传递整个reducer,这可能完全没问题,但如果reducer中有很多数据对组件没有任何影响,那么性能将会降低,因为你将强制React在没有必要更新组件时更新组件。


1
更符合“Redux”思想的方法是向存储器中分派一个操作以更新状态,并让Redux重新渲染您的组件。您现在的做法不被认为是良好的实践。
问题在于组件状态将与存储器不同步,因此,如果存储器被更新并触发重新渲染,则组件可能会收到新的属性(如果没有其他内容更新state.PassageReducer,则可能不会),并覆盖本地状态。
请查看Redux文档中有关“单向数据流”的Unidirectional Data Flow和待办事项示例,其中他们add new todos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接