ReactJS:子组件不会在操作单击时触发父组件的重新渲染

时间:2018-08-08 06:58:29

标签: reactjs react-redux

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

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

// 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调用成功,单击删除按钮也无法正确地重新呈现新列表。

// 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);

为什么ListContainer组件显示不正确?

2 个答案:

答案 0 :(得分:0)

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

使用与项目有关的独特内容作为key道具。如果他们没有唯一的东西,请生成一个唯一的ID,然后将其分配给他们。

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

答案 1 :(得分:0)

有关调试(和持久性)的课程:产生大量想法并系统地对其进行测试。浏览完应用程序的每个角落之后,我发现了问题!问题出在展示层。重构后, react-transition-group 无法正常工作。删除 TransitionGroup CSSTransition 可以解决此问题。