React Redux-Form 使用 child 组件和具有多个提交的 child 组件

React Redux-Form using child components with child components that have multiple submits

新 React-Redux。

我有一个 child 组件,该组件将以下内容与 "handleSubmit" 结合使用,这部分代码有效。

        <span
        style={textLinkStyle}
        onClick={handleSubmit(values =>
          props.onSubmit({
            ...values,
            sortBy: 'ClientNumber'
          }
          ))}>
        <span>Client # </span>
      </span>

这是上面代码的 child 组件以及所有相关部分。

export const TableHeaders = (props) => {
  const { handleSubmit } = props

  const { sortBy, sortDirection } = props

  return (
    <div>
      <div className="row">
        <div className="col-md-2" style={headingCellStyle}>
          <span
            style={textLinkStyle}
            onClick={handleSubmit(values =>
              props.onSubmit({
                ...values,
                sortBy: 'ClientNumber'
              }
              ))}>
            <span>Client # </span>
          </span>

          <GlyphiconDirectionChange sortDirection={sortDirection}/>
          ......

  )
}
TableHeaders.propTypes = {
  onSubmit: PropTypes.func.isRequired,
}

const TableHeadersForm = reduxForm({
  form: 'TableHeaders',
})(TableHeaders)

export default TableHeadersForm

所以我想将这个组件的重复部分分成单独的较小组件,以便我可以重用它们。所以上面的组件现在是下面的parent

然而它也有多个提交,一个用于排序方向向上,一个用于排序方向向下...我认为它会一直传播到顶部 parent 但是唉......没有。

这是我试过的。

const GlyphiconDirectionChange = (props) => {
  const { handleSubmit } = props
  const { sortDirection } = props

  return (
    <span>
      {sortDirection === 'Descending' ?
        <span
          style={textLinkStyle}
          onClick={handleSubmit(values =>
            props.onSubmit({
              ...values,
              sortDirection: 'Ascending'
            }
            ))}
          className='glyphicon glyphicon-sort-by-attributes'>
        </span>
        :
        <span
          style={textLinkStyle}
          onClick={handleSubmit(values =>
            props.onSubmit({
              ...values,
              sortDirection: 'Descending'
            }
            ))}
          className='glyphicon glyphicon-sort-by-attributes-alt'>
        </span>
      }
    </span>
  )}

我发现 handleSubmit 在 TableHeader 组件中作为更大的 parent 组件的一部分使用时有效 - 它向下一级。一阶 child.

它在 GlyphiconDirectionChange 组件中不起作用。第二个订单 child... 为什么?

我在控制台中收到以下错误

Exception: Call to Node module failed with error: TypeError: handleSubmit is not a function

这是语法错误。我应该如何处理 "handleSubmit",同时在 child 的一部分也是 child 组件时发送更新的值。

所以回顾一下。 HandleSubmit 在 child 中工作,但在 child 组件的 child 中不工作。第二层向下...

编辑

我注意到#Dennis 建议我使用发送而不是使用 handleSubmit。这是完整的 ClientsContainer:

import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import Clients from './Clients'
import SearchClients from './SearchClients'
import TableHeaders from './TableHeaders'
import { requestClients } from './reducer'

class ClientsContainer extends Component {
  static contextTypes = {
    router: PropTypes.object.isRequired
  }

  componentDidMount() {
    if (!this.props.isAuthorised) {
      this.context.router.push('/')
      return
    }

    this.fetchClients()
  }

  fetchClients = (values = {}) => {
    const { currentPage, query, sortBy, sortDirection } = this.props
    const searchParams = {
      currentPage,
      query,
      sortBy,
      sortDirection,
      ...values,
    }
    console.log('fetchClients()!', values, searchParams)
    this.props.requestClients(searchParams)
  }

  clientsSearch = (values = {}) => {
    const { query, sortBy, sortDirection } = this.props
    values.query = values.query || ''
    const searchParams = {
      query,
      sortBy,
      sortDirection,
      ...values,
      currentPage: 1,
    }
    console.log('clientsSearch()!', values, searchParams)
    this.fetchClients(searchParams)
  }

  changeHeaders = (values = {}) => {
    const { query, sortBy, sortDirection } = this.props
    values.query = values.query || ''
    const searchParams = {
      query,
      sortBy,
      sortDirection,
      ...values,
      currentPage: 1,
    }
    console.log('changeHeaders()!', values, searchParams)
    this.fetchClients(searchParams)
  }

  handlePageChanged = (pageIndex) => {
    this.fetchClients({
      currentPage: pageIndex,
    })
  }

  render() {
    const { clients, currentPage, query, sortBy, sortDirection, totalClients, totalPages } = this.props

    return (
      <div className="row">
        <div className="col-md-12">
          <SearchClients onSubmit={this.clientsSearch}
            currentPage={currentPage}
            query={query}
            sortBy={sortBy}
            sortDirection={sortDirection}
          />
          <TableHeaders onSubmit={this.changeHeaders}
            currentPage={currentPage}
            query={query}
            sortBy={sortBy}
            sortDirection={sortDirection}
          />
          <Clients clients={clients}
            currentPage={currentPage}
            query={query}
            sortBy={sortBy}
            sortDirection={sortDirection}
            totalClients={totalClients}
            totalPages={totalPages}
            onPageChanged={this.handlePageChanged}
          />
        </div>
      </div>
    )
  }
}

const mapStateToProps = (state) => ({
  isAuthorised: state.login.isAuthorised,
  clients: state.clients.clients,
  currentPage: state.clients.currentPage,
  query: state.clients.query,
  sortBy: state.clients.sortBy,
  sortDirection: state.clients.sortDirection,
  totalClients: state.clients.totalClients,
  totalPages: state.clients.totalPages,
})
const mapDispatchToProps = (dispatch) => ({
  requestClients: (values) => dispatch(requestClients(values)),
})
export default connect(mapStateToProps, mapDispatchToProps)(ClientsContainer)

它确实有发送到减速器的地方。再次..如果我想将一个表单组件化为许多组件,其中一个可能是 header 即 link.. 当它可能是组件的一个组件时,最好的方法是什么的 parent 组件,目前是唯一发送...

是否绝对有必要提交排序说明之类的内容,或者在某种程度上与您的后端相关?在我看来,这应该是对客户的责任。

将它留给客户端还有一个额外的好处,那就是让这一切变得更加简单,因为当您想要更改排序方向时,您可以只发送一个常规操作。然后该操作可以使用请求的排序方向调用您的后端,并且可以相应地更新新状态。

根据您要处理的数据量,您甚至可以选择完全不调用后端并将排序完全留给客户端。

关于您的 TableHeaders 组件,我会这样做:

让组件通过 props 接受事件处理函数,这样您就可以在组件内部的排序发生变化时通知容器。

这适用于更小的组件,因为您只是通过 props 传递函数。

简化示例:

export const TableHeaders = (props) => {
  const { onSortByChange, onSortDirectionChange } = props;

  return (
    <div>
      <span onClick={() => onSortByChange('ClientNumber')}>Client #</span>
      <span onClick={() => onSortByChange('SomethingElse')}>Something else</span>

      <GlyphiconDirectionChange onSortDirectionChange={onSortDirectionChange} />
    </div>
  );
}

const GlyphiconDirectionChange = (props) => {
  const { onSortDirectionChange } = props;

  return (
    <div>
      <span onClick={() => onSortDirectionChange('asc')}>Asc</span>
      <span onClick={() => onSortDirectionChange('desc')}>Desc</span>
    </div>
  );
}

然后在你的容器中你可以这样做:

class ClientsContainer extends Component {
  handleSortDirection = (direction) => {
    // Call Redux action to update your sort direction state
  }

  handleSortBy = (by) => {
    // Call Redux action to update your sort by state
  }

  render() {
    return (
      <div>
        <TableHeaders
          onSortByChange={this.handleSortBy}
          onSortDirectionChange={this.handleSortDirection}
          /* other props */
        />
      </div>
    );
  }
}

为了获取新数据,您可以实现 componentWillUpdate 并检查排序依据或排序方向是否已更改,如果已更改,则根据更新的属性获取新数据。

但是,我觉得将它和数据获取部分从您的组件移动到异步动作创建器中会更优雅。这样你的组件的责任就更少了。