如何在状态更改时更新组件

时间:2018-02-16 03:03:12

标签: javascript arrays reactjs

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;
}
}

任何帮助都非常感谢。

2 个答案:

答案 0 :(得分:1)

fetchTweets函数现在无法正常工作的原因是因为twitter.get函数是异步,这意味着回调后的内容不会在调用之后立即发生。它发生了一会儿。这是你打电话时发生的事情:

  • 创建alltweets数组,设置为[]
  • twitter.get被称为
  • alltweets数组返回到反应组件
  • 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 })
  })
}

答案 1 :(得分:0)

方法不是很好。

让您的函数theProject返回使用数据解析的承诺或拒绝错误。

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); } }); }); }; 拨打this.useUsername(),而是在其中调用submitHandler并在其中调用fetchTweets

setState

或者,如果您也可以尝试async / await而不是承诺链。