簡體   English   中英

狀態更改時如何更新組件

[英]How to update component when state changes

Heyia,這里的React noob,對於可能愚蠢的問題感到抱歉,我是幾天前才剛開始的,無法真正解決這個問題。

我正在創建一個包含從Twitter API獲取的數據的對象數組,並將其發送回我想進一步使用它的App組件。

我得到了數組,將其設置為App組件的狀態,但是無法實現更改立即顯示在頁面上–我的意思是在從用戶輸入獲得用戶名並由返回數組的函數處理后立即打印列表。

這可能很簡單,但我還沒有完全掌握組件之間的通信及其生命周期的想法(如果相關,我不確定),所以我無法弄清楚。

有人可以幫幫我嗎?

這是我的代碼

App.js文件

class App extends Component {

constructor(props) {
    super(props);
    this.state = {
        username: "",
        tweets: []      // here I need to get the array of objects
    };

    this.submitHandler = this.submitHandler.bind(this);
}

// following methods are used to first get a username by user input

submitHandler = (event) => {
    event.preventDefault();
    this.useUsername();
};

usernameChangeHandler = (event) => {
    this.setState({username: event.target.value});
};

// this one's calling the function for obtaining the tweets, code below

useUsername = () => {
    this.setState({tweets: fetchTweets(this.state.username)});
};

render() {
    return (
        <div className="App">
            <Grid fluid>
                <Row>
                    <form>
                        <label>
                            Username:
                            <input type="text" value={this.state.username} onChange={this.usernameChangeHandler}/>
                        </label>
                        <button type="submit" onClick={this.submitHandler.bind(this)}>Submit</button>
                    </form>
                </Row>
                <Row>
                    <div className="jumbotron text-center">

                         // this should be updated when state changes
                        <Table list={this.state.tweets}/>
                    </div>
                </Row>
            </Grid>
        </div>
    );
}
} 

const Table = ({list}) => {
return (
    <div>
        {
            list.map((item) =>
                <div key={item.id}>
                    <h3>{item.text}</h3>
                    <h4>by {item.author}</h4>
                    <h5>by {item.date}</h5>
                    <p>{item.num_of_likes} Likes; Mentions: {item.mentions}; Hashtags: {item.hashtags}</p>
                </div>
            )
        }
    </div>
)
};

函數處理用戶輸入並返回數組

export const fetchTweets = username => {
let alltweets = [];
twitter.get('statuses/user_timeline', {screen_name: username, count: 50}, function (error, tweets, response) {
    if (!error) {
        for (let i = 0; i < 50; i++) {
            let tw = tweets[i];
            let newtweet = new Tweet(i, tw.text, tw.user.screen_name, tw.created_at,
                tw.favorite_count, tw.entities.user_mentions, tw.entities.hashtags);
            alltweets.push(newtweet);
        }
    } else {
        console.log("Error occurred while retrieving tweets: " + error);
        return error;
    }
});
        return alltweets;

};

這是我根據Twitter數據創建的對象類別

export class Tweet {
constructor(id, text, author, date, num_of_likes, mentions, hashtags) {
    this.id = id;
    this.text = text;
    this.author = author;
    this.date = date;
    this.num_of_likes = num_of_likes;
    this.mentions = mentions;
    this.hashtags = hashtags;
}
}

任何幫助,高度贊賞。

fetchTweets函數現在無法正常工作的原因是因為twitter.get函數是異步的 ,這意味着回調函數在調用后不會立即發生。 稍后會發生。 調用時會發生以下情況:

  • 創建alltweets數組,並將其設置為[]
  • twitter.get被稱為
  • alltweets數組返回到react組件
  • React將狀態設置為空數組
  • twitter.get完成,得到結果,並向數組添加內容

這里缺少的部分是setState需要 twitter.get完成之后而不是之前完成。 實現此目的最直接的方法是允許fetchTweets函數接受另一個函數,該函數在twitter.get完成時被調用。 這樣做的方法如下:

// new fetchTweets
export const fetchTweets = (username, handleResult) => {
  twitter.get("statuses/user_timeline", { screen_name: username, count: 50 }, function(error, tweets, response) {
    if (!error) {
      let alltweets = []

      for (let i = 0; i < 50; i++) {
        let tw = tweets[i]
        let newtweet = new Tweet(i, tw.text, tw.user.screen_name, tw.created_at, tw.favorite_count, tw.entities.user_mentions, tw.entities.hashtags)
        alltweets.push(newtweet)
      }

      // callback function is called here
      handleResult(alltweets)
    } else {
      console.log("Error occurred while retrieving tweets: " + error)
    }
  })
}

// in your react component
useUsername = () => {
  fetchTweets(this.state.username, alltweets => {
    this.setState({ tweets: alltweets })
  })
}

做法不好。

使函數fetchTweets返回以數據解析的承諾或以錯誤拒絕的承諾。

export const fetchTweets = username => {
  let alltweets = [];
  return new Promise((resolve, reject) => {
    twitter
      .get('statuses/user_timeline', {
        screen_name: username,
        count: 50
      }, function (error, tweets, response) {
        if (!error) {
          ///construct alltweets

          resolve(alltweets);
        } else {
          reject(error);
        }
      });
  });
};

而不是從submitHandler調用this.useUsername()submitHandler調用fetchTweets並在其中設置setState

submitHandler = (event) => {
  event.preventDefault();
  fetchTweets().then((alltweets) => {
    this.setState({tweets: alltweets})
  }).catch((error) => console.log(error));
};

或者,如果您也可以嘗試async / await而不是諾言鏈。

暫無
暫無

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

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