簡體   English   中英

對項目范圍做出反應

[英]React Setting State to Scope of Item

我正在嘗試學習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和樣式更改。

因此,我是否設置了錯誤的狀態以將狀態保持在范圍之內,或者只是缺少一次僅更新一次單擊就更新一顆星的功能?

兩種可能的方法:

* 我會選擇第二個,因為當您單擊單個項目時,它不會重新顯示整個新聞列表。

1.單擊<FontAwesomeIcon />可使單擊的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保留在<Card /> ,而是將每個新聞項轉換為單個<NewsItem />組件。

只有一個組件,您可以應用與代碼示例相同的邏輯。 因此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>
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM