处理器影响第一个按钮上的所有行单击

时间:2017-07-18 06:35:46

标签: javascript reactjs redux

我有一个用户表,每行都包含一个重置密码链接。

当我单击表格中的第一个按钮(每行都有该按钮)时,它会命中我的处理程序(它存在于我的容器中...我的容器将处理程序作为道具传递下去)它正在击中我的处理程序{{1 }}

但是在try / catch之后调用handleResetPassword中的setState()时,它会更新状态,这意味着我的低级组件会收到该状态的通知。因为我正在更新它说因为某些原因出现了错误,尽管所有行都看到了更新状态,因此每行上的每个按钮最终显示出来。我只想要点击的按钮来显示它,而不是全部:

UserContainer.js

handleResetPassword

UserList.js

import { connect } from 'react-redux'
import React, { Component } from 'react'

import * as UserAsyncActions from '../actions/Users/UserAsyncActions'
import Users from '../components/Users/UserList'

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

    this.state = {
      resetPasswordError: null
    }

    this.handleResetPassword = this.handleResetPassword.bind(this)
  }
  async componentDidMount() {
    await this.props.allUsers(this.props.token)
  }

  async handleResetPassword(uuid) {

    // console.log(e.current.target)
    console.log("handleResetPassword invoked!")
    try {
      await this.props.resetUserPassword()
      if(this.props.hasResetPassword){
        // show successful message (set message here)
        return
      }
    }
    catch(err) {
      this.setState({
        resetEmailValidationState: 'error',
        resetPasswordError: !this.state.hasResetPassword && 'reset failed'
      })
    }

    this.setState({
      resetEmailValidationState: 'error',
      resetPasswordError: !this.state.hasResetPassword &&
      'reset failed'
    })
  }

  render(){
    return (
      <Users
        handleResetPassword={this.handleResetPassword}
        resetPasswordError={this.state.resetPasswordError}
        users={this.props.users}
      />)
  }

}
export const mapStateToProps = state => ({
  isRequestingAllUsers: state.user.isRequestingAllUsers,
  hasResetPassword: state.user.hasResetPassword,
  users: state.user.users,
  token: state.auth.token
})

export const mapDispatchToProps = {
  allUsers: UserAsyncActions.allUsers,
  resetUserPassword: UserAsyncActions.resetPasssord
}

export { Users }
export default connect(mapStateToProps, mapDispatchToProps)(UsersContainer)

注意点击第一个按钮后,如何触及handleResetPassword,并在其中设置状态:

this.setState({           resetEmailValidationState:'error',           resetPasswordError:!this.state.hasResetPassword&amp;&amp;           '重置失败'         })

好吧,现在每个按钮最终显示错误消息,而不是仅显示我点击的第一个按钮:

enter image description here

这是screencast of it happening

1 个答案:

答案 0 :(得分:0)

您控制按钮道具的状态会传递给您的<Users />组件,然后该组件会将同一道具传递给<UserList />,然后再将同一道具传递给每个<User /> 。单击按钮时,它会更改<UsersContainer />中的状态,导致resetPasswordError prop在所有按钮中更改。

您需要在容器的状态中为每个按钮指定一个索引,以便单独切换或为每个<User />设置一个容器。

编辑:

好的,我会为你的<UserList />创建一个带连接的容器组件。映射您的handleResetPassword方法以分派resetPassword操作。 (你应该提取这个动作,你必须编写reducer。)这里的想法是保持对UserList中所有用户的引用,并且每个用户都有一个resetPasswordError属性,除非出现错误,否则该属性为null。如果出现错误,请使用handleResetPassword方法向用户的uuid分派操作。在reducer中,您可以更新用户的状态。以下是一些代码示例。

const mapStateToProps = ( state ) => {
    return {
        users: state.users
    };
};
const mapDispatchToProps = ( dispatch ) => {
    return {
        handleResetPassword: ( uuid ) => {
            dispatch({
                type: "RESET_USER_PASSWORD",
                uuid
            })
        }
    };
};

let UserList = ({ users, handleResetPassword }) => {
    const userList = users && users.map(
        ( user ) => (
            <User
                key={ user.uuid }
                user={ user }
                handleResetPassword={ handleResetPassword }
                resetPasswordError={ user.resetPasswordError }
            />
        )
    ); 

    return(
        <Table responsive >
            <thead>
                <tr>
                    <th>uuid</th>
                    <th>First</th>
                    <th>Last</th>
                    <th>email</th>
                </tr>
            </thead>
            <tbody>{ userList }</tbody>
        </Table>
    );
};
export UserList = connect( mapStateToProps, mapDispatchToProps )( UserList );

export const User = ({ user, resetPasswordError, handleResetPassword }) => {
    const { uuid, firstName, lastName, email } = props.user;
    return (
        <tr>
            <td>{ uuid }</td>
            <td>{ firstName }</td>
            <td>{ lastName }</td>
            <td>{ email }</td>
            <td>
                <HelpBlock disabled={ resetPasswordError ? true : false }>
                    { resetPasswordError }
                </HelpBlock>
                <Button onClick={ () => handleResetPassword( uuid ) }>
                    reset password
                </Button>
            </td>
        </tr>
    );
};