【问题标题】:React Setting State to Scope of Item将设置状态反应到项目范围
【发布时间】:2019-03-16 20:17:28
【问题描述】:

我正在尝试学习 React 并构建一个从 Reddit API 中提取的简单应用程序。我现在要做的是添加一个虚拟星形按钮,该按钮以空白开头并带有边框,并且在单击时被填充,就像用户能够喜欢该帖子一样。我最初将 start 的状态设置为 false ,当用户单击 start 时,状态设置为 true 并切换星形的样式。我现在的问题是,当它被点击时,它正在做我想要它做的事情,但是正在改变每个帖子的明星风格,而不仅仅是点击它的一个帖子。所以我想要做的是将状态保持在星号被点击的帖子项目的范围内。这是我的代码目前的样子:

import React, { Component } from 'react';
import './Card.css';

import axios from 'axios';
import SortControls from './SortControls/SortControls';

import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'

import { faStar as faStarRegular } from '@fortawesome/free-regular-svg-icons';
import { faStar as faStarSolid } from '@fortawesome/free-solid-svg-icons';

library.add(
  faStarRegular,
  faStarSolid
)
class Card extends React.Component {
    state = {
        news: [],
        starActive: false,
    };


componentDidMount() {
    axios.get(`https://www.reddit.com/r/funny/hot.json`).then(res => {
        console.log(res);
        this.setState({news: res.data.data.children});
    })
}

render() {


    return (
        <div className="container">
        <SortControls />
        <div className="cards">
            {this.state.news.map((newsItems, i) =>
           <div key={newsItems.data.id} className="card">
           <div className="cardHead"><h3>{newsItems.data.title}</h3></div>
           <div className="cardFooter">
                <div className="cardFooter__container">
                    <a href="#">View</a>
                    <FontAwesomeIcon onClick={() => this.setState({starActive: !this.state.starActive})} icon={ this.state.starActive ? ['fas', 'star'] : ['far', 'star'] } />

                </div>
            </div>
           </div>)}
        </div>
        </div>

    )
}

}


export default Card;

您可以在 FontAwesomeIcon 组件上看到我的 onClick 和样式更改。

那么我是否设置错误以将状态保持在范围内,或者我只是缺少一些东西来一次只更新一颗星?

【问题讨论】:

    标签: javascript reactjs font-awesome


    【解决方案1】:

    两种可能的方法:

    * 我更喜欢第二个,因为当您单击单个项目时,它不会重新呈现整个新闻列表。

    1。当您单击 &lt;FontAwesomeIcon /&gt; 以保持单击的 newsItems id 处于状态时。

    this.toggleId(id) {
      const { activeIds } = this.state
    
      if (activeIds.includes(activeIds)) {
        return this.setState({ activeIds: activeIds.filter(i => i !== id) })
      }
    
      this.setState({ activeIds: [...activeIds, id] })
    }
    
    // Render method ...
    const { activeIds } = this.state
    
    <FontAwesomeIcon
      onClick={() => this.toggleId(newsItems.data.id)}
      icon={ activeIds.includes(newsItems.data.id) ? ['fas', 'star'] : ['far', 'star'] } />
    

    2。不要将所有点击的 id 保存在 &lt;Card /&gt; 中,而是将每个新闻项转换为单个 &lt;NewsItem /&gt; 组件。

    只有一个组件,您可以应用与代码示例相同的逻辑。因此starActive 标志只会影响单个组件。

    类似的东西:

    // Cards render
    <div className="cards">
      { this.state.news.map((newsItem, i) => (
        <NewsItem {...newsItem} key={newsItem.data.id}  />
      ))}
    </div>
    
    // NewsItem
    class NewsItem extends React.Component {
      state = {
        starActive: false,
      }
    
      render() {
        const { data } = this.props
    
        return <div key={data.id} className="card">
          <div className="cardHead"><h3>{data.title}</h3></div>
            <div className="cardFooter">
              <div className="cardFooter__container">
                 <a href="#">View</a>
                 <FontAwesomeIcon
                   onClick={() => this.setState({
                     starActive: !this.state.starActive
                   })}
                   icon={ this.state.starActive ? ['fas', 'star'] : ['far', 'star'] } />
               </div>
            </div>
          </div>
       </div>
      }
    }
    

    【讨论】:

    • 我更喜欢第二种方法来保持状态分开
    • 太棒了,效果很好!我选择了选项 2,以使事情更加分开。感谢您的帮助!
    猜你喜欢
    • 2016-12-05
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    • 2017-01-18
    • 1970-01-01
    相关资源
    最近更新 更多