2017-04-19 23 views
0

React-Redux的新手。React Redux-Form使用包含多个提交子组件的子组件

我有一个子组件,它使用下面的“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唉..不。

这就是我试过的。

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> 
)} 

我发现那是什么时候的的tableHeader组件作为一个更大的父组件的一部分handleSubmit作品 - 它的下一层。第一个订单的孩子。

它在GlyphiconDirectionChange组件中不起作用。第二个孩子......为什么?

我得到以下错误控制台

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

这是一个语法错误。我应该如何处理“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) 

它确实有发送,它是减速机的地方。再次..如果我想组成一个表单到许多组件中,其中一个可能是一个链接的标题..什么是最好的方式来做到这一点,当它可能是父组件的一个组件的组件是唯一一个派遣...

+0

我已经使用特定于您的用例的示例更新了原始答案。 – Dennis

回答

1

是否绝对有必要提交像排序方向的东西,或者是在某种程度上与您的后端相关?在我看来,这应该是客户的责任。

把它放到客户端还有一个额外的好处,使所有这一切变得更加简单,因为您可以在您想要更改排序方向时发送常规操作。然后,该操作可以按照请求的排序方向调用后端,并且可以相应地更新新状态。

根据您处理的数据量的不同,您甚至可以选择根本不打电话给您的后端,并将整个分拣留给客户端。

关于你TableHeaders组件,这里就是我会做:

有分量接受通过道具的事件处理函数,这样你就可以通知容器时,在组件内部的排序变化。

这对于更小的组件来说很好,因为你只是通过道具传递函数。

简单的例子:

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并检查排序或排序方向已经改变,如果是这样,根据更新的道具获取新数据。

但是,我觉得将它和数据提取部分从组件转移到异步操作创建者会更优雅。这样你的组件就没有什么责任了。

+0

Backend是一个ASP.NET API。后端为搜索/过滤器排序和排序方向提供响应。它还提供分页。当您点击tableHeader组件中的标题时,我进行了排序工作。剥离标题和方向标记组件正在将我扼杀在这里,因为它现在是一个孩子的孩子。 – si2030

+0

这仍然很好,我实际上正在用C#WebApi后端工作一个类似的项目。我会去掉现在用于排序的'handleSubmit'东西,并且只是定期发送Redux动作。就像我说的,这些可以是(异步)动作创建者,接受排序方向,然后从API中获取排序数据。然后,您可以使用新提取的数据更新商店。你的组件也会自动更新,因为它的道具将被更新。 – Dennis

+0

我相信这是一个好方法,我会为它投票。尽管GlyphiconDirection中的值的实际设置发生了变化,但我仍然遇到麻烦,因此ClientContainer中的ChangeHeaders(上述)功能可以使用设置值。我已经放置了控制台日志,它只是提出'ClientNumber'..给定有一些道具需要也包括在内(但不要改变)我应该得到类似于changeDirection()的consoleLog! Object {sortBy:“Client”} Object {query:“test”,sortBy:“LastName”,sortDirection:“Descending”,currentPage:1} .. – si2030