javascript - 当一个组件的状态发生变化时,如何防止整个列表重新呈现?

标签 javascript reactjs bootstrap-4

我有一个列表组件,它获取数据并将结果映射到类似卡片的子组件以创建“卡片”列表。下面是一个例子:

class Card extends Component {
  constructor(props) {
    super(props);
    this.state = {
      activeTab: 1
    };
  }

  setActiveTab = (activeTab) => {
    this.setState({ activeTab });
  }

  render() {
    const activeTab = this.state.activeTab;

    return (
      <div className="card">
        <ul className="nav nav-tabs card-header-tabs">
          <li 
            className="nav-item" 
            key={ 1 }
            onClick={ () => this.setActiveTab(1) }
          >
            <a className="nav-link" href="#">Overview</a>
          </li>
          <li 
            className="nav-item" 
            key={ 2 }
            onClick={ () => this.setActiveTab(2) }
          >
            <a className="nav-link" href="#">Data</a>
          </li>
          <li 
            className="nav-item" 
            key={ 3 }
            onClick={ () => this.setActiveTab(3) }
          >
            <a className="nav-link" href="#">Edit</a>
          </li>
        </ul>
        <h3 className="card-title">{ this.props.title }</h3>
        { activeTab === 1 && 
          <h5 className="card-text">
            { this.props.body }
          </h5>    
        }
        { activeTab === 2 && 
          <div className="card-data">
            <a>Yes: { this.props.yes }</a>
            <a>No: { this.props.no }</a>
          </div>
        }
        { activeTab === 3 &&
          <div>
            <a 
              href="/cards"
              onClick={ this.props.onDelete }
              className="delete-card"
            >
              Delete
            </a>
          </div>
        }
      </div>
    )
  }
}
export default Card;


class CardList extends Component {
  componentDidMount() {
    this.props.fetchCards();
  }

  renderCards() {
    return this.props.cards.reverse().map(({ _id, title, body, yes, no }) => {
      return (
        <Card
          key={_id}
          title={title}
          body={body}
          yes={yes}
          no={no}
          onDelete={() => this.props.deleteSurvey(_id)}
        />
      );
    });
  }

  render() {
    return (
      <div className="container">
        <div className="row">{this.renderCards()}</div>
      </div>
    );
  }
}

每张卡片都有选项卡,单击选项卡可确定每张特定卡片中显示的文本。选项卡/切换正在工作,但我的问题是单击选项卡时整个列表正在重新呈现。因此,如果您位于列表底部,重新渲染会将您带回到列表顶部。

我已经尝试实现 componentShouldUpdate,但到目前为止没有成功。我想让卡片切换它的内容并且列表保持不变。使用 shouldUpdate 生命周期方法是否正确?或者有更好的方法吗?

最佳答案

在你的<a> anchor 标签,你有 href="#"`,它总是将你重定向到一个新的链接。 (# 将重定向到当前页面并重新呈现所有内容)。

Easiest Solution is to remove href="#" which will remove your cursor: pointer; styling but you can re-add that back into your nav-item classname.

另一个简单的解决方案是您可以将 onClick 移动到 anchor 标记中并添加 evt.preventDefault()(这会阻止事件处理程序从执行将页面加载到 href 的 default 操作)但是这将使您必须单击 anchor 标记,因此如果您在 <li> 之间有填充和 <a>这可能不是您的最佳解决方案。

<li 
  className="nav-item"
  key={ 3 } 
>
  <a 
    className="nav-link" 
    href="#" 
    onClick={ (e) => { e.preventDefault(); this.setActiveTab(3); } }
  >
    Edit
  </a>
</li>

但是 Thai Duong Tran 提出了一个很好的观点,即您不想每次都重新创建函数。

Best solution is to move your anonymous function into a class function. (This solution also removes the href="#" so you need to add cursor: pointer; into your css if you want that style)

 <li 
   className="nav-item" 
   data-tab={ 1 }
   onClick={this.onNavClick}
 >
   <a className="nav-link">Overview</a>
 </li>

 onNavClick = (evt) => {
   this.setState({activeTab: evt.target.dataset.tab});
 }

您的删除操作也存在与您添加 href="/card"相同的问题,因此您要小心处理。

如果你想让路由操作移动到不同的页面/URL。您应该考虑添加 react-router

关于javascript - 当一个组件的状态发生变化时,如何防止整个列表重新呈现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49663155/

相关文章:

javascript - RefreshControl with ScrollView 每次刷新都会向下移动屏幕内容

reactjs - 以编程方式聚焦并选择 react 选择中的值

javascript - 如何使用 ReactJS 将变量值添加到属性?

html - 如何将文本放在卡片组上方?

angular - 网页包/Angular 2 : specify order of styles

javascript - 带有列表组的 Bootstrap 4 scrollspy 不起作用

javascript - 在 GraphQL 中将参数从根查询传递到子查询

javascript - 正确更新 D3 饼图

javascript - Apache NiFi 1.3 : How would I approach passing sets of vin #s through the htsa. dot.gov API?

javascript - 将代码标签内的代码复制到剪贴板reactJS