【问题标题】:Render all elements after updating state in one with Redux在使用 Redux 更新状态后渲染所有元素
【发布时间】:2019-12-03 21:16:40
【问题描述】:

我有一个小问题 在我更新数组中一个元素的状态后,我需要渲染所有元素,即使是那些没有改变其状态的元素。

我有 Waiter 组件,其中带有状态按钮,我正在更新一张桌子的状态。

class Waiter extends React.Component {
  static propTypes = {
    fetchTables: PropTypes.func,
    loading: PropTypes.shape({
      active: PropTypes.bool,
      error: PropTypes.oneOf(PropTypes.bool,PropTypes.string),
    }),
    tables: PropTypes.any,
    postTableStatus: PropTypes.func,

  }

  componentDidMount(){
    const { fetchTables } = this.props;
    fetchTables();
  }

  onClick(e, tableId, status, order) {
    e.preventDefault();

    if(status === 'free'){
      status = 'thinking';
    }
    else if(status === 'thinking'){
      status = 'ordered';
    }
    else if(status === 'ordered'){
      status = 'prepared';
    }
    else if(status === 'prepared'){
      status = 'delivered';
    }
    else if(status === 'delivered'){
      status = 'paid';
    }
    else if(status === 'paid'){
      status = 'free';
    }

    this.props.postTableStatus(tableId, status, order);

  }

  renderActions(status, id, order){
    switch (status) {
      case 'free':
        return (
          <>
            <Button onClick={(e) => this.onClick(e, id, status, order)}>thinking</Button>
            <Button onClick={(e) => this.onClick(e, id, status, order)}>new order</Button>
          </>
        );
      case 'thinking':
        return (
          <Button onClick={(e) => this.onClick(e, id, status, order)}>new order</Button>
        );
      case 'ordered':
        return (
          <Button onClick={(e) => this.onClick(e, id, status, order )}>prepared</Button>
        );
      case 'prepared':
        return (
          <Button onClick={(e) => this.onClick(e, id, status, order)}>delivered</Button>
        );
      case 'delivered':
        return (
          <Button onClick={(e) => this.onClick(e, id, status, order)}>paid</Button>
        );
      case 'paid':
        return (
          <Button onClick={(e) => this.onClick(e, id, status, order)}>free</Button>
        );
      default:
        return null;
    }
  }

  render() {
    const { loading: { active, error }, tables } = this.props;
    console.log('props',this.props);
    if(active || !tables.length){
      return (
        <Paper className={styles.component}>
          <p>Loading...</p>
        </Paper>
      );
    } else if(error) {
      return (
        <Paper className={styles.component}>
          <p>Error! Details:</p>
          <pre>{error}</pre>
        </Paper>
      );
    } else {
      return (
        <Paper className={styles.component}>
          <Table>
            <TableHead>
              <TableRow>
                <TableCell>Table</TableCell>
                <TableCell>Status</TableCell>
                <TableCell>Order</TableCell>
                <TableCell>Action</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {tables.map(row => (
                <TableRow key={row.id}>
                  <TableCell component="th" scope="row">
                    {row.id}
                  </TableCell>
                  <TableCell>
                    {row.status}
                  </TableCell>
                  <TableCell>
                    {row.order && (
                      <Button to={`${process.env.PUBLIC_URL}/waiter/order/${row.order}`}>
                        {row.order}
                      </Button>
                    )}
                  </TableCell>
                  <TableCell>
                    {this.renderActions(row.status, row.id, row.order)}
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </Paper>
      );
    }
  }
}

当 Waiter 组件正在加载时,一切都呈现良好。但是在我更新一张桌子后全部卡在 Loading...

这是我的 WaiterContainer.js

const mapStateToProps = state => ({
  tables: getAll(state),
  loading: getLoadingState(state),
});

const mapDispatchToProps = dispatch => ({
  fetchTables: () => dispatch(fetchFromAPI()),
  postTableStatus: (table, status, order) => dispatch(putToTableStatus(table, status, order)),
});


export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Waiter);

和tablesRedux.js 文件

/* selectors */
export const getAll = ({ tables }) => tables.data;
export const getLoadingState = ({ tables }) => tables.loading;
export const postOrderStatus = ({ tables }) => tables.status;

/* action name creator */
const reducerName = 'tables';
const createActionName = name => `app/${reducerName}/${name}`;

/* action types */
const FETCH_START = createActionName('FETCH_START');
const FETCH_SUCCESS = createActionName('FETCH_SUCCESS');
const FETCH_ERROR = createActionName('FETCH_ERROR');
const POST_STATUS = createActionName('POST_STATUS');


/* action creators */
export const fetchStarted = payload => ({ payload, type: FETCH_START });
export const fetchSuccess = payload => ({ payload, type: FETCH_SUCCESS });
export const fetchError = payload => ({ payload, type: FETCH_ERROR });
export const postStatus = payload => ({ payload, type: POST_STATUS });


/* thunk creators */
export const fetchFromAPI = () => {
  return (dispatch, getState) => {
    dispatch(fetchStarted());

    Axios.get(`${api.url}/${api.tables}`)
      .then(res => {
        dispatch(fetchSuccess(res.data));
      })
      .catch(err => {
        dispatch(fetchError(err.message || true));
      });
  };
};
// tableId, newStatus, newOrder
export const putToTableStatus = (tableId, newStatus, newOrder) => {
  return (dispatch, getState) => {
    Axios.patch(`${api.url}/${api.tables}/${tableId}`, {status: newStatus, order: newOrder})
      .then(res => {
        console.count('table spread',tableId);
        console.count(' status',newStatus);
        console.count(' order',newOrder);
        dispatch(postStatus(res.data));
        console.log('data', res.data);
        console.log('postStatus1',postStatus(res.data));
      });
  };
};

/* reducer */
export default function reducer(statePart = [], action = {}) {
  switch (action.type) {
    case FETCH_START: {
      return {
        ...statePart,
        loading: {
          active: true,
          error: false,
        },
      };
    }
    case FETCH_SUCCESS: {
      return {
        ...statePart,
        loading: {
          active: false,
          error: false,
        },
        data: action.payload,
      };
    }
    case POST_STATUS: {
      return{
        ...statePart,
        data: action.payload,
      };
    }

    default:
      return statePart;
  }
}

我更新前的道具是 6 个表的数组

tables: Array(6)
0: {id: 1, status: "thinking", order: null}
1: {id: 2, status: "thinking", order: null}
2: {id: 3, status: "free", order: 1234}
3: {id: 4, status: "free", order: 3647}
4: {id: 5, status: "free", order: 12340}
5: {id: 6, status: "free", order: 45207}
length: 6

但更新后我得到的只是我刚刚更新的表

tables:
id: 4
order: 3647
status: "thinking"

不知道如何让它工作:/ 这是最新的提交Link

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    我猜这是因为您在这里完全覆盖了减速器中的数据以进行 POST_STATUS 操作,而不是仅仅覆盖您更改的一个表。

    尝试更改此设置

    case POST_STATUS: {
          return{
            ...statePart,
            data: action.payload,
          };
        }
    

    到这里

    case POST_STATUS: {
          return {
            ...statePart,
            data: [
              ...statePart.data.filter((table) => table.id !== action.payload.id), 
              action.payload
            ],
          };
        }
    

    这样您应该返回所有旧表,以及您更改的表的最新数据。

    编辑: 这不会保留顺序,如果您需要在编辑后不重新排序数组,请尝试以下操作:

    case POST_STATUS: {
          const editedIndex = statePart.data.findIndex((table) => table.id === action.payload.id);
          return {
            ...statePart,
            data: [
              ...statePart.data.slice(0, editedIndex),
              action.payload
              ...statePart.data.slice(editedIndex + 1)
            ],
          };
        }
    

    【讨论】:

    • 谢谢。第一部分正在工作,但是当我使用未重新排序代码的部分时,它说“数据”未定义
    • 对不起,不是“数据”未定义,而是Cannot read property 'findIndex' of undefined
    • 糟糕,应该是statePart.data 而不是statePart.filter,我会编辑答案
    猜你喜欢
    • 1970-01-01
    • 2016-04-22
    • 2020-09-03
    • 2023-03-19
    • 2017-03-26
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多