#17 React-redux 实现用户列表的显示、增加、删除


  • 1

    @胡子大哈
    通过测试了,哈哈哈。


  • 0

    这是我只是主要 写了下 connect action的思路,仅此而已.并没有给按钮绑定增删方法。仅供参考,有错误还望支持。

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const userReducer = (state={},action)=>{
      switch(action.type){
        case "ADD_ITEM":
          return {...state, userList:[...state.userList,action.item]};
        case "SUBSTRACT_ITEM":
          delete state.userList[action.index];
          return {...state, userList:[...state.userList]};
        default:
          return state;
      }
    }
    
    const store = createStore(userReducer,{});
    
    const Add_item_action = (itemObj)=>return {type:"ADD_ITEM",item:itemObj};
    const Substract_item_action = (index)=>return {type:"SUBSTRACT_ITEM",index:index};
    
    
    class User extends Component {
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button>删除</button>
          </div>
        )
      }
    }
    
    
    const mapPropsToState = (state)=>{
      return {userList:state.userList};
    }
    const mapPropsToDispatch = (dispatch)=>{
      return {
        addHandle:(item)=>dispacth(Add_item_action(item)),
        substructHandle:(index)=>dispatch(Substract_item_action(index))
      }
    }
    
    
    const UserListComponent = connect(mapPropsState,mapPropsToDispatch)(UserList);
    
    class UsersList extends Component {
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' /></div>
              <div>Age: <input type='number' /></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' /></label>
                <label>Female: <input type='radio' name='gender' value='female' /></label>
              </div>
              <button>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {
                const that = this;
                return (
                    this.props.userList.mpa((item)=>{
                       return(
                         <User username={item.username} age={item.age} gender={item.gender} />
                       )
                     })
                 )
              }
            </div>
          </div>
        )
      }
    }
    

  • 0

    @ScriptOJ 胡子哥,请教一下!这个题目的输入框没必要搞成受控组件吧?我觉得直接通过 ref 得到组件DOM,然后取值,重置值也挺方便的。而搞成受控组件还需要绑定 onchange 事件,同时也需要重置 state,并没有优雅多少。是不是这个例子太简单所以看不出差别?


  • 0

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const usersReducer = (state = [], action) => {
      switch (action.type) {
        case 'ADD_USER': 
          return [...state, action.user];
        case 'DELETE_USER':
          return [...state.slice(0, action.index), ...state.slice(action.index+1)];
        case 'UPDATE_USER':
          return [...state.slice(0, action.index), {...state[action.index], ...action.user}, ...state.slice(action.index+1)]
        default:
          return state;
      }
    }
    
    class User extends Component {
      render () {
        const { user, deleteUser, index } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={()=> {deleteUser(user, index)}}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      state = {
        gender: '',
      }
      
      handleSubmit = () => {
        this.props.addUser({
          username: this.usernameRef.value,
          age: Number(this.ageRef.value),
          gender: this.state.gender,
        })
      }
      
      handleRadioClick = (e) => {
        const gender = e.target.value;
        this.setState({gender});
      }
      
      render () {
        const { users, deleteUser } = this.props
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' ref={r => this.usernameRef = r} /></div>
              <div>Age: <input type='number' ref={r => this.ageRef = r}/></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onClick={this.handleRadioClick} /></label>
                <label>Female: <input type='radio' name='gender' value='female' onClick={this.handleRadioClick} /></label>
              </div>
              <button onClick={this.handleSubmit}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {users.map((user, index)=>
                <User user={user} deleteUser={deleteUser} index={index} key={index}/>
              )}
            </div>
          </div>
        )
      }
    }
    
    const mapStateToProps = (state) => {
      return {
        users: state   
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        addUser: (user) => {
          dispatch({
            type: 'ADD_USER',
            user
          })
        },
        deleteUser: (user, index) => {
          dispatch({
            type: 'DELETE_USER',
            index: index,
            user
          })
        }
      }
    }
    
    UsersList = connect(
      mapStateToProps,
      mapDispatchToProps
    )(UsersList)
    

  • 0

    @ScriptOJ 请教一下 提示:新增用户以后,应该返回新的数组

     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const usersReducer = (state = [],action) => {
      switch(action.type) {
        case 'add':
          return [...state,action.payload]
        case 'delete':
          return [...state.slice(0,action.index),...state.slice(action.index + 1)]
        default:
          return state
      }
    }
    
    class User extends Component {
      render () {
        const { user,deleteOne,index } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={() => this.deleteOne(index)}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor() {
        this.state = {
          username:'',
          age:'',
          gender:''
        }
      }
      handleUsername(e) {
        this.setState({
          username:e.target.value
        })
      }
      handleAge(e) {
        this.setState({
          age:Number(e.target.value)
        })
      }
      handleGender(e) {
        this.setState({
          gender:e.target.name
        })
      }
      addUser() {
        let {addUser} = this.props
        addUser(this.state)
        this.setState((prvState,nextprops) => {
          return {
            username:'',
            age:'',
            gender:''
          }
        })
      }
      render () {
        let {deleteOne,list} = this.props
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' onInput={(e) => this.handleUsername(e)} value={this.state.username} /></div>
              <div>Age: <input type='number' onInput={(e) => this.handleAge(e)} value={this.state.age} /></div>
              <div>Gender:
                <label>Male: <input onClick={(e) => this.handleGender(e)} type='radio' name='gender' value='male' value={this.state.gender} /></label>
                <label>Female: <input onClick={(e) => this.handleGender(e)} type='radio' name='gender' value='female' value={this.state.gender} /></label>
              </div>
              <button onClick={this.addUser.bind(this)}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
            {
              /* TODO */
              list.map((item,key) => <User deleteOne={deleteOne} index={key} username={item.username} age={item.age} gender={item.gender} key={key} />)
            }
            </div>
          </div>
        )
      }
    }
    
    let mapStateToProps = (state) => {
      return {
        list:state
      }
    }
    let mapDispatchToProps = (dispatch,getState) => {
      return {
        addUser:function(user) {
          dispatch({
            type:'add',
            payload:user
          })
        },
        delete:function(index) {
          dispatch({
            type:'delete',
            index:index
          })
        }
      }
    }
    
    connect(mapStateToProps,mapDispatchToProps)(UsersList)
    

  • 0

     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
      const usersReducer = (state, action)=> {
        if(!state){
            return []
        }
        let newState = [...state]   // 另一种复制数组的方法
        switch(action.type){
            case 'ADD_USER':
                newState.push(action.user)  
                break
            case 'DELETE_USER':
                newState.splice(action.index, 1)
                break
            case 'UPDATE_USER':
                const oldUser = newState[action.index]
                const newUser = action.user
                newState[action.index] = {...oldUser, ...newUser}
                break
            default:
                return state    // 需要原封不动地返回,不然会直接返回一个全新的数组
        }
        return newState
    }
    
    class User extends Component {
    static propTypes = {
      user: PropTypes.object,
      onDeleteUser: PropTypes.func
    }  
    handleDeleteUser(){
      if(this.props.onDeleteUser){
        this.props.onDeleteUser(this.props.idx)
      }
    }
    render () {
      const { user } = this.props
      return (
        <div>
          <div>Name: {user.username}</div>
          <div>Age: {user.age}</div>
          <div>Gender: {user.gender}</div>
          <button onClick={this.handleDeleteUser.bind(this)}>删除</button>
        </div>
      )
    }
    }
    const mapDispatchToProps1 = (dispatch) => {
    return {
      'onDeleteUser':(idx) => {
        dispatch({type:'DELETE_USER', index:idx})
      }
    }
    }
    User = connect(null, mapDispatchToProps1)(User)
    class UsersList extends Component {
    static propTypes = {
      usersList: PropTypes.array,
      onAddUser: PropTypes.func
    }
    constructor(){
      super()
      this.state = {
        // user: { // 这样好清理  // 会出现不可控的警告
        //   userName: '',
        //   age: 0
        // }
        username:'',
        age: '',
        gender: ''
      }
    }
    handleAddUser(){
      if(this.props.onAddUser){
        const user = {
          username: this.state.username,
          age:  parseInt(this.state.age),
          gender: this.state.gender
        }
        this.props.onAddUser(user)
        this.setState({userName:'',age:'',gender:''})  // 清空用户输入
      }
    }
    handleTypeName(event){
      this.setState({
        username:event.target.value
      })  
    }
    handleTypeAge(event){
      this.setState({
        age:event.target.value
      })  
    }
    
    handleGender(event){
      this.setState({
        gender:event.target.value
      })
    }
    render () {
      return (
        <div>
          {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
          <div className='add-user'>
            <div>Username: <input type='text' value={this.state.username} onChange={this.handleTypeName.bind(this)}/></div>
            <div>Age: <input type='number' value={this.state.age} onChange={this.handleTypeAge.bind(this)} /></div>
            <div>Gender:
              <label>Male: <input type='radio' name='gender' value='male'  onClick={this.handleGender.bind(this)} /></label>
              <label>Female: <input type='radio' name='gender' value='female' onClick={this.handleGender.bind(this)} /></label>
            </div>
            <button onClick={this.handleAddUser.bind(this)}>增加</button>
          </div>
          {/* 显示用户列表 */}
          <div className='users-list'>{this.props.usersList.map((user, idx)=>{
            return <User key={idx} idx={idx} user={user} />
          })}</div>
        </div>
      )
    }
    }
    const mapStateToProps = (state) => {
      return {
          usersList: state  // 有提示过usersReducer 的 state 就是一个数组
      }  
    }
    const mapDispatchToProps2 = (dispatch) => {  
      return {
        'onAddUser':(user) => {
          dispatch({type:'ADD_USER', user:user})
        }
      }
    }
    UsersList = connect(mapStateToProps, mapDispatchToProps2)(UsersList)
    

    给个通过的答案给大家参考,请多指教(有一点点不完美,清空输入时单选框没控制好)


  • 0

    未通过,提示不懂。。。。

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const userReducer = (state, action) => {
      if (!state) {
        return []
      }
      switch (action.type) {
        case ADD_USER: 
          return [...state, {...action}]
        case DELETE_USER:
          const newState = [...state]
          newState.filter((item) => {
            return item.username !== action.username
          })
          return newState
        default:
          return state
      }
    }
    
    const store = createStore(userReducer)
    
    class User extends Component {
      static propTypes = {
        onDeleteUser: PropTypes.func,
        user: PropTypes.object
      }
      
      handleDeleteUser (username) {
        if (this.props.onDeleteUser) {
          this.props.onDeleteUser(username)
        }
      }
      
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={this.handleDeleteUser.bind(this, user.username)}>删除</button>
          </div>
        )
      }
    }
    
    const mapDispathProps = dispath => {
      return  {
        onDeleteUser (username) => {
          dispath({
            type: 'DELETE_USER',
            username,
          })
        }
      }
    }
    
    User = connect(null, mapDispathProps)(User)
    
    class UsersList extends Component {
      static propTypes = {
        onAddUser: PropTypes.func,
        userList: PropTypes.array
      }
      
      constructor () {
        super()
        this.state = {
          user: {
            name: '',
            age: '',
            gender: ''
          }
        }
      }
      
      handleAddUser () {
        if (this.props.onAddUser) {
          this.props.onAddUser(this.state.user)
        }
      }
      
      handleName (e) {
        this.setState({
          ...this.state.user,
          name: Number(e.target.value)
        })
      }
      
      handleAge (e) {
        this.setState({
          ...this.state.user,
          age: e.target.value
        })
      }
      
      handleGender (e) {
        this.setState({
          ...this.state.user,
          gender: e.target.value
        })
      }
      
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' value={this.state.user.name} onChange={this.handleName}/></div>
              <div>Age: <input type='number' value={this.state.user.age} onChange={this.handleAge}/></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onChange={this.handleGender.bind(this)}/></label>
                <label>Female: <input type='radio' name='gender' value='female' onChange={this.handleGender.bind(this)}/></label>
              </div>
              <button onClick={this.handleAddUser.bind(this)}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>{this.props.usersList.map((item, index) => {
              <User {...item} key={index} />
            })}</div>
          </div>
        )
      }
    }
    
    const mapStateProps = state => {
      return {
        usersList: state
      }
    }
    const mapDispathPropsAddUser = dispath => {
      return {
        onAddUser(userObj) {
          dispath({
            type: 'ADD_USER',
            userObj,
          })
        }
      }
    }
    
    UsersList = connect(mapStateProps, mapDispathPropsAddUser)(UsersList)
    
    
    

  • 0

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const usersReducer = (state = [], action) => {
      switch (action.type) {
        case 'ADD_USER':
          return [...state, action.user]
        case 'DELETE_USER':
          return [...state.slice(0, action.index), ...state.slice(action.index + 1)]
        case 'UPDATE_USER':
          return [...state.slice(0, action.index), {...state[action.index], ...action.user}, ...state.slice(action.index + 1)]
        default:
          return state
      }
    }
    
    class User extends Component {
      constructor() {
        super()
        this.handleDeleteUser = this.handleDeleteUser.bind(this)
      }
      
      handleDeleteUser() {
        const { index, onDeleteUser } = this.props
        if (onDeleteUser) {
          onDeleteUser(index)
        }
      }
      
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={this.handleDeleteUser}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor() {
        super()
        this.state = {
          username: '',
          age: '',
          gender: ''
        }
        
        this.handleUsernameChange = this.handleUsernameChange.bind(this)
        this.handleAgeChange = this.handleAgeChange.bind(this)
        this.handleGenderChange = this.handleGenderChange.bind(this)
        this.handleAddUser = this.handleAddUser.bind(this)
      }
      
      handleUsernameChange(evt) {
        this.setState({
          username: evt.target.value
        })
      }
      
      handleAgeChange(evt) {
        this.setState({
          age: Number(evt.target.value)
        })
      }
      
      handleGenderChange(evt) {
        this.setState({
          gender: evt.target.value
        })
      }
      
      handleAddUser() {
        if (this.props.onAddUser) {
          this.props.onAddUser(this.state)
        }
      }
    
      render () {
        const { username, age } = this.state
        const { users, onDeleteUser } = this.props
        const usersListNode = users.map((user, index) => {
          return <User key={index} index={index} user={user} onDeleteUser={onDeleteUser} />
        })
    
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' value={username} onChange={this.handleUsernameChange} /></div>
              <div>Age: <input type='number' value={age} onChange={this.handleAgeChange} /></div>
              <div onChange={this.handleGenderChange}>Gender:
                <label>Male: <input type='radio' name='gender' value='male' /></label>
                <label>Female: <input type='radio' name='gender' value='female' /></label>
              </div>
              <button onClick={this.handleAddUser}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>{usersListNode}</div>
          </div>
        )
      }
    }
    
    const mapStateToProps = state => {
      return {
        users: state
      }
    }
    
    const mapDispatchToProps = dispatch => {
      return {
        onAddUser: user => {
          dispatch({
            type: 'ADD_USER',
            user: user
          })
        },
        onDeleteUser: index => {
          dispatch({
            type: 'DELETE_USER',
            index: index
          })
        }
      }
    }
    
    UsersList = connect(mapStateToProps, mapDispatchToProps)(UsersList)
    

  • 0

    终于搞定了,整个过程其实很简单,只是被困在parseInt那个坑里好久 T_T...

    const usersReducer = (state, action) => {
        if (!state)
            return []
        switch (action.type) {
            case 'ADD_USER':
            return [...state, action.user]
            case 'DELETE_USER':
            return [...state.slice(0, action.index), ...state.slice(action.index+1) ]
            case 'UPDATE_USER':
            const newUser = {...state[action.index], ...action.user}
            return [...state.slice(0, action.index), newUser, ...state.slice(action.index+1) ]
            default:
            return state
        }
    }
    
    class User extends Component {
      render () {
        const { user, onDelUser, index } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={()=>{onDelUser(index)}}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
        static propTypes = {
            onAddUser: PropTypes.func,
            onDelUser: PropTypes.func,
            users: PropTypes.array
        }
    
      constructor() {
        super()
        this.state = {
          username: '',
          age: 18,
          gender: 'male'
        }
        this.handleInputChange = this.handleInputChange.bind(this)
      }
    
      // 这种处理多个输入源的方式是从react官网看来的,比较简洁!
      // https://reactjs.org/docs/forms.html#handling-multiple-inputs
      handleInputChange(event) {
        const name = event.target.name
        // 这个坑。。。大家小心,其实在应用中不用parseInt也可以的
        if (name === "age") {
          this.setState({
            [name]: parseInt(event.target.value)
          })
        } else {
          this.setState({
            [name]: event.target.value
          })
        }
      }
      
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' name='username' value={this.state.username} onChange={this.handleInputChange} /></div>
              <div>Age: <input type='number' name='age' value={this.state.age} onChange={this.handleInputChange} /></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onChange={this.handleInputChange} /></label>
                <label>Female: <input type='radio' name='gender' value='female' onChange={this.handleInputChange} /></label>
              </div>
              <button onClick={()=>{this.props.onAddUser(this.state)}}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
            {this.props.users.map((user, i) => {
              return <User key={i} index={i} user={user} onDelUser={this.props.onDelUser} />
            })}
            </div>
          </div>
        )
      }
    }
    
    const mapStateToProps = (state) => {
      return ({users: state})
    }
    
    const mapDispatchToProps = (dispatch, props) => {
      return ({
        onAddUser: (user) => {
          dispatch({
            type: 'ADD_USER',
            user: user
          })
        },
        onDelUser: (index) => {
          dispatch({
            type: 'DELETE_USER',
            index: index
          })
        }
      })
    }
    
    UsersList = connect(mapStateToProps, mapDispatchToProps)(UsersList)
    

  • 0

    考察Redux的:

    • 定义
    • 与react的结合

    也考察了React组件的基本写法与form的一些理念。好题目。


  • 0

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const usersReducer = (state, action) => {
      if (!state) state = []
      switch (action.type) {
        case 'ADD_USER':
          state = [...state, action.user]
          break
        case 'DELETE_USER':
          state = state.filter((u, i) => action.index !== i)
          break
        case 'UPDATE_USER':
          state = state.map((u, i) => (action.index === i) ? {...u, ...action.user} : u)
          break
      }
      
      return state
    }
    
    class User extends Component {
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={this.props.onDel}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      state = {
        username: '',
        age: undefined,
        gender: undefined
      }
      onInputChange = (evt) => {
        let { target: { name, value} }  = evt
        if (name === 'age') value = Number(value)
        this.setState(() => ({
          [name]: value
        }))
      }
      
      handleClick = () => {
        this.props.onAdd(this.state)
      }
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' 
                name="username" 
                value={this.state.username}
                onChange={this.onInputChange}
                />
              </div>
              <div>Age: <input type='number' 
                name="age"
                value={this.state.age}
                onChange={this.onInputChange}
                />
              </div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' 
                  onChange={this.onInputChange}/></label>
                <label>Female: <input type='radio' name='gender' value='female' 
                  onChange={this.onInputChange}/></label>
              </div>
              <button onClick={this.handleClick}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {
                this.props.list.map((u, i) => <User key={i} user={u} onDel={() => {this.props.onDel(i)}}/>)
              } 
            </div>
          </div>
        )
      }
    }
    
    
    UsersList = connect(state => ({
      list: state
    }),
    dispatch => ({
      onAdd: (user) => dispatch({ type: 'ADD_USER', user}),
      onDel: (index) => dispatch({ type: 'DELETE_USER', index}),
    }))(UsersList)
    
    
    

  • 0

    在本地一直都是成功的,但是在平台上就显示新增后返回新数组... 好吧我没审好题,要直接使用那个 usersReducer 。。。要有 'UPDATE_USER' 。。。。磨了这么久。。。。。。

    
    const usersReducer = (state = [], action) => {
      switch (action.type) {
        case 'ADD_USER': {
          return [...state, action.user];
        }
        case 'DELETE_USER': {
          let newState = [...state]
          newState.splice(action.index, 1)
          return newState;
        }
        case 'UPDATE_USER':
          let upState = [...state];
          upState[action.index] = {...upState[action.index], ...action.user};
          return [...upState];
        default:
          return state
      }
      return state
    }
    
    // const usersReducer = (state=[], action) => {
    //   switch (action.type) {
    //     case 'ADD_USER': 
    //       return [...state, action.user];
    //     case 'DELETE_USER':
    //       let deState = [...state];
    //       deState.splice(action.index, 1);
    //       return [...deState];
    //     case 'UPDATE_USER':
    //       let upState = [...state];
    //       upState[action.index] = {...upState[action.index], ...action.user};
    //       return [...upState];
    //     default:
    //       return state;
          
    //   }
    // }
    
    class User extends Component {  
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={() => this.props.onButtonClick(this.props.index)}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor () {
        super()
        this.state = {
          username: '',
          age: 0,
          gender: ''
        }
      }
      
      handleInputChange (prop, e) {
        var value = e.target.value
        if (prop === 'age') value = parseInt(value)
        this.setState({
          [prop]: value
        })
      }
      
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: 
                <input type='text' 
                  value={this.state.username}
                  onChange={this.handleInputChange.bind(this, 'username')} />
              </div>
              <div>Age: 
                <input type='number' 
                  value={this.state.value} 
                  onChange={this.handleInputChange.bind(this, 'age')} />
              </div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' 
                  onClick={this.handleInputChange.bind(this, 'gender')} /></label>
                <label>Female: <input type='radio' name='gender' value='female'
                  onClick={this.handleInputChange.bind(this, 'gender')} /></label>
              </div>
              <button onClick={() => this.props.addUser(this.state)}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {this.props.userList.map(
                (user, index) => <User user={user} key={index} index={index} onButtonClick={this.props.deleteUser.bind(this)}/>)
              }
            </div>
          </div>
        )
      }
    }
    
    const mapStateToProps = (state) => {
      console.log(state)
      return {
        userList: state
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        addUser: (user) => {
          dispatch({
            type: 'ADD_USER',
            user: user
          })
        },
        deleteUser: (index) => {
          dispatch({
            type: 'DELETE_USER',
            index
          })
        }
      }
    }
    
    UsersList = connect(mapStateToProps, mapDispatchToProps)(UsersList)
    

  • 0

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const ADD_USER = "ADD_USER"
    const DELETE_USER = "DELETE_USER"
    const UPDATE_USER = "UPDATE_USER"
    
    const usersReducer = (state = [], action) => {
      switch(action.type) {
        case 'ADD_USER':
          return [...state, action.user];
        case 'DELETE_USER':
          return state.filter((item, index) => index !== action.index);
        case 'UPDATE_USER':
          return [...state.map((item, index) => {
            if (index === action.index) {
              return { ...item, ...action.user }
            } else {
              return item
            }
          })]
        default:
          return state;
      }
    }
    
    class User extends Component {
      handleDelete = index => {
        this.props.deleteUser(index)
      }
      render () {
        const { user, index } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={() => this.handleDelete(index)}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      state = {
        username: '',
        age: '',
        gender: '',
      }
      handleChangeName = e => {
        const username = e.target.value
        this.setState({ username })
      }
      handleChangeAge = e => {
        const age = Number(e.target.value)
        this.setState({ age })
      }
      handleChangeGender = e => {
        const gender = e.target.value
        this.setState({ gender })
      }
      handleAdd = () => {
        this.props.addUser(this.state)
      }
      render () {
        const { username, age, gender } = this.state
        const { addUser, deleteUser, users } = this.props
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' value={username} onChange={this.handleChangeName} /></div>
              <div>Age: <input type='number' value={age} onChange={this.handleChangeAge} /></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onChange={this.handleChangeGender} /></label>
                <label>Female: <input type='radio' name='gender' value='female' onChange={this.handleChangeGender} /></label>
              </div>
              <button onClick={this.handleAdd}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {
                users.map((item, index) => {
                  return <User user={item} deleteUser={deleteUser} index={index} key={index} />
                })
              }
            </div>
          </div>
        )
      }
    }
    
    const mapStateToProps = state => ({ users: state })
    const mapDispatchToProps = (dispatch, state) => {
      return {
        addUser: user => {
          dispatch({
            type: 'ADD_USER',
            user: user,
          })
        },
        deleteUser: index => {
          dispatch({
            type: 'DELETE_USER',
            index: index,  
          })
        }
      }
    }
    
    UsersList = connect(
      mapStateToProps,
      mapDispatchToProps
    )(UsersList)
    
    

  • 0

    @陈小俊#17 React-redux 实现用户列表的显示、增加、删除 中说:

    class User extends Component {
      render () {
        const { user, onDeleteUser, index} = this.props
        return (
          <div>
            <div>Name: {user.userName}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={()=> {onDeleteUser(user, index)}}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor() {
        super();
        this.state = {
          index: 0,
          userName: '',
          age: '',
          gender: ''
        }
      }
      
      render () {
        const { userName, age, gender } = this.state
        const { onAddUser, onDeleteUser, users } = this.props
    
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' value={userName} onChange={e=>{this.setState({userName: e.target.value})}} /></div>
              <div>Age: <input type='number' value={age} onChange={e=>{this.setState({age: e.target.value})}} /></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onChange={e=>{this.setState({gender: e.target.value})}} /></label>
                <label>Female: <input type='radio' name='gender' value='female' onChange={e=>{this.setState({gender: e.target.value})}} /></label>
              </div>
              <button onClick={()=>{this.setState({index: this.state.index+1});onAddUser(this.state)}}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {users.map((user, index)=>
                <User user={user} onDeleteUser={onDeleteUser.bind(this)} index={index} key={index}/>
              )}
            </div>
          </div>
        )
      }
    }
    
    
    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    const mapStateToProps = (state) => {
      return {
        users: state   
      }
    }
    
    const mapDispatchToProps = (dispatch) => {
      return {
        addUser: (user) => {
          dispatch({
            type: 'ADD_USER',
            user
          })
        },
        deleteUser: (user, index) => {
          console.log(index)
          dispatch({
            type: 'DELETE_USER',
            index: index,
            user
          })
        }
      }
    }
    
    class UsersContainer extends Component {
    
      render () {
        return (
          <UsersList
            users={this.props.users}
            onAddUser={this.props.addUser.bind(this)}
            onDeleteUser={this.props.deleteUser.bind(this)}
          />
        )
      }
    }
    
    const usersReducer = connect(
      mapStateToProps,
      mapDispatchToProps
    )(UsersContainer)

  • 0

    我的为什么一直提示state应该初始化为一个空数组谁能帮我看下

     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
    
    const usersReducer = (state, {type, user, index}) => {
      if(!state){
        return {
          users: []
        }
      }
      const users = [...state.users]
      switch(type) {
        case 'ADD_USER':
          return [...users, user]
        case 'DELETE_USER':
          users.splice(index, 1)
          return users
        case 'UPDATE_USER':
          users.splice(index, 1, {...users[index], ...user})
          return users
        default:
        return state
      }
    }
    
    class User extends Component {
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={() => this.props.onDeleteUser(this.props.index)}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor() {
        super()
        this.state = {
          username: '',
          age: '',
          gender: ''
        }
      }
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input onChange={({target: {value: username}}) => this.setState({username})} type='text' /></div>
              <div>Age: <input onChange={({target: {value: age}}) => this.setState({age})}type='number' /></div>
              <div>Gender:
                <label>Male: <input onChange={({target: {value: gender}}) => this.setState({gender})} type='radio' name='gender' value='male' /></label>
                <label>Female: <input type='radio' name='gender' value='female' /></label>
              </div>
              <button onClick={() => this.props.onAddUser(this.state)}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>{this.props.users.map((user, i) => <User key={i} index={i} user={user}/>)}</div>
          </div>
        )
      }
    }
    
    const mapStateToProps = ({users}) => ({ users })
    const mapDispatchToProps = dispatch => ({
      onAddUser(user) {
        dispatch({type: 'ADD_USER', user})
      },
      onDeleteUser(index) {
        dispatch({type: 'DELETE_USER', index})
      }
    })
    
    UsersList = ReactRedux.connect(mapStateToProps, mapDispatchToProps)(UsersList)
    

  • 0

    有没有大佬能帮忙看一下,好像并没有执行dispatch内的方法

    /**
     * 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
     */
     
    const usersReducer = (state, action) => {
      if(!state){
        return []
      }
      switch(action.type){
        case 'ADD_USER':
          return [...state, action.user]
        case 'DEL_USER':
          return [...state, state.splice(action.index, 1)]
        default:
          return state
      }
    }
    
    class User extends Component {
      handleDel(){
        if(this.props.onDel){
          this.props.onDel(this.props.index)
        }
      }
      render () {
        const { user } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={this.handleDel.bind(this)}>删除</button>
          </div>
        )
      }
    }
    
    class UsersList extends Component {
      constructor(){
        super()
        this.state = {
          username: '',
          age: '',
          gender: ''
        }
      }
      handleInput(e){
        const target = e.target
        this.setState({
          [target.name]: target.value
        })
      }
      handleSubmit(){
        if (this.props.onSubmit){
          this.props.onSubmit(this.state.username, this.state.age, this.state.gender)
        }
      }
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' name='username' value='this.state.username' onChange={this.handleInput.bind(this)} /></div>
              <div>Age: <input type='number' name='age' value='this.state.age' onChange={this.handleInput.bind(this)} /></div>
              <div>Gender:
                <label>Male: <input type='radio' name='gender' value='male' onChange={this.handleInput.bind(this)} /></label>
                <label>Female: <input type='radio' name='gender' value='female' onChange={this.handleInput.bind(this)} /></label>
              </div>
              <button onClick={this.handleSubmit.bind(this)}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>
              {this.props.users.map((user, index)=>{
                return <User user={user} key={index} index={index} />
              })}
            </div>
          </div>
        )
      }
    }
    const mapStateToProps = (state) => {
      return{
        state
      }
    }
    const mapDispatchToProps = (dispatch) => {
      return {
        onSubmit({username, age, gender}){
          dispatch({ type: 'ADD_USER', user: {username, age, gender} })
        },
        onDel(index){
          dispatch({ type: 'DEL_USER', index: index })
        }
      }
    }
    
    UsersList = connect(mapStateToProps, mapDispatchToProps)(UsersList)
    User = connect(null, mapDispatchToProps)(User)
    
    

  • 0

    @我上来就是一Jo reducer里面 if(!state)的情况下应该初始化为空数组[],而不是一个含有users属性的对象


  • 0

    const usersReducer = (state=[],action)=>{
      switch(action.type){
        case 'ADD_USER':
          return [...state,action.user]
          break;
        case 'DELETE_USER':
          return [...state.slice(0,action.index),...state.slice(action.index+1)]
          break;
        case 'UPDATE_USER':
          return [...state.map((item,i)=>{
            if(i === action.index){
              return {...item,...action.user}
            } else {
              return item
            }
          })]
          break;
        default:
        return state
        break;
      }
    }
    
    const store = createStore(usersReducer)
    
    class User extends Component {
      
      handleDelete(index){
        if(this.props.onDelete){
          this.props.onDelete(index)
        }
      }
      render () {
        const { user,index } = this.props
        return (
          <div>
            <div>Name: {user.username}</div>
            <div>Age: {user.age}</div>
            <div>Gender: {user.gender}</div>
            <button onClick={this.handleDelete.bind(this,index)}>删除</button>
          </div>
        )
      }
    }
    
    
    class UsersList extends Component {
      
      state={
        username: '',
        age: '',
        gender: '',
      }
      
      onInputChange = (e) => {
        switch(e.target.type){
          case 'text':
            this.setState({
              username: e.target.value
            })
            break;
          case 'number':
            this.setState({
              age: parseInt(e.target.value)
            })
          break;
          case 'radio':
            this.setState({
              gender: e.target.value
            })
          break;
          
        }
      }
      
      handleAdd = () => {
        if(this.props.onAdd){
          let {username, age, gender} = this.state
          this.props.onAdd({username, age, gender})
        }
      }
    
      render () {
        return (
          <div>
            {/* 输入用户信息,点击“新增”按钮可以增加用户 */}
            <div className='add-user'>
              <div>Username: <input type='text' onChange={this.onInputChange}/></div>
              <div>Age: <input type='number' onChange={this.onInputChange}/></div>
              <div onChange={this.onInputChange}>Gender:
                <label>Male: <input type='radio' name='gender' value='male' /></label>
                <label>Female: <input type='radio' name='gender' value='female' /></label>
              </div>
              <button onClick={(e)=>this.handleAdd()}>增加</button>
            </div>
            {/* 显示用户列表 */}
            <div className='users-list'>{
              this.props.users.map((user,index)=>{
                return <User {...this.props} user={user} index={index} />
              })
            }</div>
          </div>
        )
      }
    }
    
    function mapStateToProps(state){
      return {
        users: state,
      }
    }
    
    function mapDispatchToProps(dispatch){
      return {
        onAdd: (user)=>{
          dispatch({type:'ADD_USER',user})
        },
        onDelete: (index)=>{
          dispatch({type:'DELETE_USER',index})
        }
      }
    }
    
    UsersList = connect(mapStateToProps,mapDispatchToProps)(UsersList)
    

  • 0

    /**

    • 环境中已经注入了 React-redux,你可以直接使用 connect,或者 ReactRedux.connect
      */

    const userReducer = (state, action) => {
    switch (action.type) {
    case "ADD_USER":
    return {
    users: [...state.users, action.user]
    }
    case "DEL_USER":
    let users = [...state.users];
    users.splice(action.index, 1);
    return {
    users: users
    }
    default:
    return {
    users: []
    };
    }
    };

    const mapStateToProps = state => {
    return {
    users: state.users
    };
    };

    const mapDispatchToProps = dispatch => {
    return {
    addUser: user => {
    console.log("user", user);
    dispatch({
    type: "ADD_USER",
    user: user
    });
    },
    delUser: index => {
    dispatch({
    type: "DEL_USER",
    index: index
    });
    }
    };
    };

    class User extends React.Component {
    render() {
    let { user, index } = this.props;
    return (
    <div>
    <div>序号: {index}</div>
    <div>Name: {user.username}</div>
    <div>Age: {user.age}</div>
    <div>Gender: {user.gender}</div>
    <button onClick={() => {
    this.props.delUser(this.props.index)
    }}>删除</button>
    </div>
    );
    }
    }

    User = connect(
    null,
    mapDispatchToProps
    )(User);

    class UsersList extends React.Component {
    constructor() {
    super();
    this.state = {
    username: "",
    age: 0,
    gender: ""
    };
    }

    handleChange = event => {
    const { name, type, value } = event.target;
    this.setState({
    [name]: type === "number" ? +value : value
    });
    };

    handleAddUser = () => {
    this.props.addUser({
    ...this.state
    });
    }
    render() {
    return (
    <div>
    {/* 输入用户信息,点击“新增”按钮可以增加用户 /}
    <div className="add-user">
    <div>
    Username:
    <input
    type="text"
    value={this.state.username}
    name="username"
    onChange={this.handleChange}
    />
    </div>
    <div>
    Age:
    <input
    type="number"
    value={this.state.age}
    name="age"
    onChange={this.handleChange}
    />
    </div>
    <div>
    Gender:
    <label>
    Male:
    <input
    type="radio"
    name="gender"
    value="male"
    onChange={this.handleChange}
    />
    </label>
    <label>
    Female:
    <input
    type="radio"
    name="gender"
    value="female"
    onChange={this.handleChange}
    />
    </label>
    </div>
    <button onClick={this.handleAddUser}>增加</button>
    </div>
    {/
    显示用户列表 /}
    {/
    {this.props.users} /}
    {/
    <div>{[{a:1}]}</div> */}
    <div className="users-list">
    {this.props.users.map((x, index) =>
    <User user={x} index={index} key={index}/>
    )}
    </div>
    </div>
    );
    }
    }

    UsersList = connect(
    mapStateToProps,
    mapDispatchToProps
    )(UsersList);

    一直提示不是你的错,那是啥错 --


  • 0

    @bpqpqp#17 React-redux 实现用户列表的显示、增加、删除 中说:

    那些提示“修改用户以后,应该返回新的数组”的要在usersReducer加上UPDATE_USER,哪怕这题跟修改用户没关系。


登录后回复
 

与 ScriptOJ 的连接断开,我们正在尝试重连,请耐心等待