当存储更改时更新组件

3

我正在尝试根据存储更新来更新组件,目标是当我点击表格项时,我希望更新表单按钮以编辑表单,并编辑表格项。

enter image description here

enter image description here

我的源代码:

我有一个动作,用于更新currentUsercurrentUser是我想要更新的用户。

src/actions/user.js

export const updateCurrentUserSuccess = (currentUser) => {
    return {
        type: UPDATE_CURRENT_USER,
        currentUser
    }
}

export const updateCurrentUser = (id) => {
    return (dispatch) => {
        return axios.get(`${apiUrl}/users/${id}`)
            .then(response => {
                console.log(response.data.data)
                dispatch(updateCurrentUserSuccess(response.data.data))
            })
            .catch(error => {
                throw (error);
            });
    };
};

我的currentUserReducer: src/reducers/currentUserReducer.js

import { UPDATE_CURRENT_USER } from '../constants/ActionTypes';

const initialState = {
    currentUser: [],
}

export default function userReducer(state = initialState, action) {
    switch (action.type) {
        case UPDATE_CURRENT_USER:
            return action.currentUser;
        default: 
            return state;
    }
}

现在我的组件:

我的新用户表单: src/components/NewUser.js

    import React, { Component } from 'react';
    import { Store } from '../store'

    class NewUser extends Component {
        state = {
            id: '',
            name: '',
            cpfcnpj: '',
            isEdit: false
        };

        componentDidMount(){
            this.handleUserChange()
        }

        handleInputChange = e => {
            this.handleUserChange();
            this.setState({
                [e.target.name]: e.target.value
            });
        };

        handleSubmit = e => {
            e.preventDefault();
            if (!this.state.isEdit) {
                if (this.state.name.trim() && this.state.cpfcnpj.trim()) {
                    this.props.onAddUser(this.state);
                    this.handleReset();
                }
            } else {
                if (this.state.name.trim() && this.state.cpfcnpj.trim() && this.state.id !== '') {
                    this.props.onEdit(this.state);
                    this.handleReset();
                }
            }

        };

        handleReset = () => {
            Store.getState().currentUser = []
            this.setState({
                id: '',
                name: '',
                cpfcnpj: '',
                isEdit: false
            });
        };

        handleUserChange() {
            console.log('store', Store.getState().currentUser._id);
            if (Store.getState().currentUser._id !== undefined) {
                this.setState({
                    id: Store.getState().currentUser._id,
                    name: Store.getState().currentUser.name,
                    cpfcnpj: Store.getState().currentUser.cpfcnpj,
                    isEdit: true
                });
            }
        }

        render() {
            return (
                <div>
                    <form className="form-inline" onSubmit={this.handleSubmit}>
                        <div className="form-group margin-right">
                            <input
                                type="text"
                                placeholder="Name"
                                className="form-control"
                                name="name"
                                onChange={this.handleInputChange}
                                value={this.state.name}
                            />
                        </div>
                        <div className="form-group margin-right">
                            <input
                                type="text"
                                placeholder="CPF/CNPJ"
                                className="form-control"
                                name="cpfcnpj"
                                onChange={this.handleInputChange}
                                value={this.state.cpfcnpj}>
                            </input>
                        </div>
                        <div className="form-group">
                            <button type="submit" className={this.state.isEdit ? "btn btn-success margin-right hidden" : "btn btn-success margin-right"}>
                                <span className="glyphicon glyphicon-plus" aria-hidden="true"></span>
                                &nbsp;
                                Adicionar
                            </button>
                            <button type="submit" className={this.state.isEdit ? "btn btn-primary margin-right" : "btn btn-primary margin-right hidden"}>
                                <span className="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>
                                &nbsp;
                                Salvar
                            </button>
                            <button type="button" className="btn btn-default margin-right" onClick={this.handleReset}>
                                <span className="glyphicon glyphicon-erase" aria-hidden="true"></span>
                                &nbsp;
                                Limpar
                            </button>
                        </div>
                    </form>
                </div>
            );
        }
    }

    export default NewUser;

my component User item:
***src/components/User.js***

import React from 'react';

export default ({ user: { name, cpfcnpj, _id }, onDelete, onEditUser }) => {
    return (
        <tr>
            <th scope="row">{name}</th>
            <td>{cpfcnpj}</td>
            <td>
                <button className="btn btn-warning btn-xs margin-right" type="button" onClick={() => onEditUser(_id)}>
                    <span className="glyphicon glyphicon-edit" aria-hidden="true"> </span>
                    &nbsp;
                    Editar
                </button>
                <button className="btn btn-danger btn-xs margin-right" type="button" onClick={() => onDelete(_id)}>
                    <span className="glyphicon glyphicon-trash" aria-hidden="true"> </span>
                    &nbsp;
                    Excluir
                </button>
            </td>
        </tr>
    );
};

现在我的智能组件:

src/containers/UserList.js

import React from 'react';
import { connect } from 'react-redux';
import User from '../components/User';
import { deleteUser, updateCurrentUser } from '../actions/user';
import NewUser from '../components/NewUser';

function UserList({ users, onDelete, onEditUser }) {
    if (!users.length) {
        return (
            <div className="margin-top">
                No Users
            </div>
        )
    }
    return (
        <div className="margin-top">
            <table className="table table-striped">
                <thead>
                    <tr>
                        <th scope="col">Nome</th>
                        <th scope="col">CPF/CNPJ</th>
                    </tr>
                </thead>
                <tbody>
                    {users.map(user => {
                        return (
                            <User user={user} onDelete={onDelete} onEditUser={onEditUser} key={user._id} />
                        );
                    })}
                </tbody>
            </table>
        </div>
    );
}

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

const mapDispatchToProps = dispatch => {
    return {
        onDelete: id => {
            dispatch(deleteUser(id));
        },
        onEditUser: (id) => {
            dispatch(updateCurrentUser(id))
        }
    };
};

export default connect(
    mapStateToProps,
    mapDispatchToProps
)(UserList, NewUser);

src/containers/CreateUser.js

import { connect } from 'react-redux';
import { createUser, updateUser } from '../actions/user';
import NewUser from '../components/NewUser';

const mapDispatchToProps = dispatch => {
    return {
        onAddUser: user => {
            dispatch(createUser(user));
        },
        onEdit: (id, name, cpfcnpj) => {
            dispatch(updateUser(id, name, cpfcnpj))
        }
    };
};

export default connect(
    null,
    mapDispatchToProps
)(NewUser);

enter image description here

src/App.js

import React, { Component } from 'react';
import CreateUser from './containers/CreateUser';
import UserList from './containers/UserList';
import './css/main.css'

class App extends Component {
  render() {
    return (
      <div className="container">
        <h1 className="styles-app">Usuários</h1>
        <div className="row styles-app">
          <div className="col-md-12">
            <CreateUser />
          </div>
          <div className="col-md-12">
            <UserList />
          </div>
        </div>
      </div>
    );
  }
}

export default App;

1
请问能否展示同时渲染表单和表格的组件呢?有几种方法可以实现,具体取决于用户更新的行为方式。这里所说的 "更新" 是指更改状态还是打开模态框? - simbathesailor
我想将列表的值放入更新表单中,而不使用模态框,只需使用已存在的表单。在这种情况下,当我点击编辑时,我希望选择列表项的值,并将其放入更新表单中,就像第二张图片中一样。 - Jefferson Bruchado
1
当您单击编辑按钮时,handleUserUpdate函数是否正确更新了NewUser.js中的状态? - seanulus
1
抱歉,handleUserChange函数。 - seanulus
不,这是我创建的一个函数,用于测试商店是否正在运行,但几乎就是这样了,我不知道如何在按钮列表UserList.js中处理此函数并移动到表单NewUser.js,因为这是两个不同的组件。 - Jefferson Bruchado
显示剩余2条评论
1个回答

2

这里有一个你可以尝试的方法。将你的NewUser.js连接到存储器。

import { connect } from 'react-redux;
export default connect(mapStateToProps)(NewUser);

然后将您的currentUser状态映射到props。
const mapStateToProps = state => {
return {
    currentUser: state.currentUser
  };
};

在你的currentUserReducer中:
initialState = {
  //Assuming these are the only values in response
  id: '',
  name: '',
  cpfcnpj: '',
  isEdit: false
};

export default function userReducer(state = initialState, action) {
switch (action.type) {
    case UPDATE_CURRENT_USER:
        return {
          ...state,
          id: action.currentUser.id,
          name: action.currentUser.name,
          cpfcnpj: action.currentUser.cpfcnpj,
          isEdit: true
        };
    default: 
        return state;
  }
}

现在您应该可以通过props访问当前用户对象。

然后在输入值字段中:

value={this.props.currentUser.name}
value={this.props.currentUser.cpfcnpj}

您可能还需要检查这些值是否已更新。此外,不确定 placeholder 文本是否会干扰。

希望这可以让您更接近解决方案。

编辑

在清除props的情况下,您只需添加另一个操作即可。 在您的currentUser操作中:

export const clearUserData = () => {
return {
    type: CLEAR_USER_DATA,
  }
}

在你的 reducer 中:

export default function userReducer(state = initialState, action) {
switch (action.type) {
case UPDATE_CURRENT_USER:
    return {
      ...state,
      id: action.currentUser.id,
      name: action.currentUser.name,
      cpfcnpj: action.currentUser.cpfcnpj,
      isEdit: true
    };
case CLEAR_USER_DATA:
  return {
      ...state,
      id: '',
      name: '',
      cpfcnpj: '',
      isEdit: false
    };
default: 
    return state;
 }
}

在提交编辑后,添加clearUserData操作以重置您的reducer。您甚至可以只执行以下操作:
return {
  ...state,
  initialState
};

它部分地起作用了,我能够在组件中使用currentUser的值作为props,现在我有一个问题,当我们有currentUser的值时,如何将UserList上编辑按钮的操作传递到NewUser组件,以将其状态isEdit更改为true。 - Jefferson Bruchado
我编辑了答案。看看reducer。我添加了id和isEdit键值对。你应该能够使用this.props.currentUser.isEdit而不是this.state.isEdit - seanulus
1
添加了另一个编辑。你需要通过mapDispatchToProps引入clearUserData操作,但那应该就可以解决问题了。 - seanulus
1
由于表单位于NewUser.js中,而您的props.currentUser是从state映射而来的,因此现在该组件中根本不需要有state。Redux正在存储与该组件中所需状态相同形状的currentUser信息。您希望使用本地状态实现的任何操作现在都可以使用props.currentUser来处理。如果您需要讨论输入的值,请使用currentUser props代替本地状态。 - seanulus
1
我明白你的意思。如果需要创建新用户,您可以将其留在那里。看起来在handleSubmit函数中,您使用本地状态添加和编辑用户。您仍然可以摆脱状态对象,因为setState将创建一个仅包含输入字段中输入值的状态对象。我想象ID是在服务器上创建的,而用于编辑的布尔值在存储中,这涵盖了这两个值。 - seanulus
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接