【问题标题】:ReactJS: Child component not triggering parent component rerender on action clickReactJS:子组件在操作单击时未触发父组件重新渲染
【发布时间】:2018-08-08 06:58:28
【问题描述】:

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

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

// 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 组件渲染不正确?

【问题讨论】:

    标签: reactjs react-redux


    【解决方案1】:

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

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

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

    【讨论】:

    • 如果id 属性对于每个项目都是唯一的,请将其用作key。
    • 谢谢,杰斯。我已经尝试过了——它确实有所作为。
    • 你能添加你的reducer代码来删除商店里的商品吗?
    • 当然,查看更新后的代码 sn-p。问题是只有当我尝试使用单独的子组件显示每个项目时才会发生错误。如果我将子组件的 JSX 移回父组件 - 一切正常。所以,我一定是错过了什么......
    • 在您的ListContainer 地图内渲染中,您有&lt;ListElement ... del={ id =&gt; this.del(id) } /&gt; id 参数来自哪里?不应该是&lt;ListElement ... del={ id =&gt; this.del(item._id) } /&gt;吗?因为它是 item 对象的一个​​属性(显然这个键看起来也有一个下划线)。
    【解决方案2】:

    调试(和持久性)课程:产生大量想法并系统地测试它们。在查看了应用程序的每个可能的角落后,我发现了问题!问题在于表示层。 react-transition-group 重构后未按预期工作。删除 TransitionGroup 和 CSSTransition 解决了这个问题。

    【讨论】:

      猜你喜欢
      • 2021-12-01
      • 2019-06-01
      • 2016-12-02
      • 1970-01-01
      • 2018-08-12
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多