使用具有多个提交的子组件的子组件来实现Redux-Form

时间:2017-04-19 06:28:27

标签: javascript reactjs redux-form

React-Redux的新功能。

我有一个子组件,它使用以下“handleSubmit”,这部分代码可以工作。

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

以上代码的子组件包含所有相关部分。

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

所以我想把这个组件的重复部分分成单独的小组件,这样我就可以重用它们了。因此,上面的组件现在是以下组件的父级。

然而,它也有多个提交一个用于排序方向向上,一个用于排序方向向下...我认为它会一直传播到顶级父级但是alac alas .. no。

这就是我的尝试。

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组件中用作较大父组件的一部分时会起作用 - 一级向下。第一顺序的孩子。

它在GlyphiconDirectionChange组件中不起作用。二阶儿童......为什么?

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

  

异常:调用节点模块失败,错误:TypeError:handleSubmit不是函数

这是语法错误。我应该如何处理“handleSubmit”,同时还发送更新的值,当它的子部分也是子组件时。

所以回顾一下。 HandleSubmit在孩子中起作用,但在子组件的子项中不起作用..第二级下来......

修改

我注意到#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)

它确实有发货,它是减速机的地方。再说..如果我想将一个表单组件化成许多组件,其中一个组件可能是一个链接头...当它可能是父组件的一个组件的组件时,最好的方法是什么是唯一一个派遣......

1 个答案:

答案 0 :(得分:1)

是否绝对有必要提交排序方向等内容,还是以某种方式与您的后端相关?在我看来,这应该是对客户的责任。

将其留给客户端还有一个额外的好处,即使所有这些变得更加简单,因为您可以在需要更改排序方向时调度常规操作。然后,该操作可以使用请求的排序方向调用您的后端,并且可以相应地更新新状态。

根据您正在处理的数据量,您甚至可以选择根本不打电话给您的后端,并将排序完全留给客户。

关于您的TableHeaders组件,以下是我要做的事情:

让组件通过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并检查排序方式或排序方向是否已更改,如果是,则根据更新的道具获取新数据。

但是,我觉得将组件中的数据提取部件移动到异步操作创建器中会更加优雅。这样你的组件的责任就会减少。