首页 > 解决方案 > ReactJS:子组件未触发父组件在操作单击时重新呈现

问题描述

我正在尝试重构我的组件并将列表项提取到一个单独的子组件中。

下面的原始代码(未重构)有效:

// ListContainer.js
import React, { Component } from 'react';
import { Container, ListGroup, ListGroupItem, Button } from 'reactstrap';
import { CSSTransition, TransitionGroup } from 'react-transition-group';

import { connect } from 'react-redux';
import { getItems, deleteItem } from '../actions/itemActions';

import PropTypes from 'prop-types';


class ListContainer extends Component {

  componentDidMount() {
        this.props.getItems();
  }

  deleteAction = (id) => {
        console.log('this.props: ' + JSON.stringify(this.props));
        this.props.deleteItem(id);
  }

  render() {

        const { items } = this.props.item;
    
        return(
          <Container>
            <ListGroup>
              <TransitionGroup className="shopping-list">
                {
                  items.map((item, i) => (
                <CSSTransition key={item._id} timeout={500} classNames="fade">
                    <ListGroupItem>
                      <Button
                        className="remove-btn"
                        color="danger"
                        size="sm"
                        onClick={e => this.deleteAction(item._id, e)}>
                        &times;
                      </Button>
                      {item.name} {item._id}
                    </ListGroupItem>
                  </CSSTransition>
                  ))
                }
              </TransitionGroup>
            </ListGroup>
          </Container>
        );
      }

}

const mapStateToProps = state => ({
  item: state.item
});

const mapDispatchToProps = dispatch => ({
  getItems: () => dispatch(getItems()),
  deleteItem: id => dispatch(deleteItem(id)),
});

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

下面的重构代码不起作用:

即使调度了操作、更新了 redux 存储并且 API 调用成功,单击删除按钮也不会正确重新呈现新列表。

// New ListContainer.js

// Same imports

// Extracted component
const ListElement = props => {
  const { del } = props;
  const { _id } = props.item;
  const { name } = props.item;
  return (
    <CSSTransition key={_id} timeout={500} classNames="fade">
      <ListGroupItem>
        <Button
          className="remove-btn"
          color="danger"
          size="sm"
          onClick={() => del(_id)}>
          &times;
        </Button>
        {name} {_id}
      </ListGroupItem>
    </CSSTransition>
  );
}

// Refactored parent component
class ListContainer extends Component {

  componentDidMount() {
    this.props.getItems();
  }

  del = (id) => {
    this.props.deleteItem(id);
  }

  render() {
    const { items } = this.props.item;

    return(
      <Container>
        <ListGroup>
          <TransitionGroup className="shopping-list">
            {
              items.map((item, i) => (
                <ListElement key={i} item={item} del={ id => this.del(id) } />
              ))
            }
          </TransitionGroup>
        </ListGroup>
      </Container>
    );
  }
}

// Same redux connector

为什么 ListContainer 组件没有正确呈现?

标签: reactjsreact-redux

解决方案


这是为什么在渲染组件列表时不应使用数组索引作为键的一个主要示例。React 无法正确检测更改。

使用物品的独特之处作为key道具。如果他们没有任何独特的东西,请生成一个独特的 id 并首先将其分配给他们。

如果您好奇,您可以研究一下为什么使用索引作为键会导致您看到的问题。可能是个好主意。


推荐阅读