【问题标题】:ReactJS - Apparent code running before fetch() has finishedReactJS - 在 fetch() 完成之前运行的明显代码
【发布时间】:2018-05-11 22:32:15
【问题描述】:

我的应用的一些背景知识:

  • 后端 - Python、Flask。该数据库目前只是嵌套的字典和列表
  • 前端 - Reactjs

我将参考的函数:

  • FetchPlayers() - 使用 fetch() 从后端获取包含所有玩家的数组。它还使用 setState() 将玩家添加到状态。
  • EditPlayer(playerid) - 使用 fetch() 向后端发出 POST 请求以更改其中一名玩家的信息。

所以当前当用户启动页面时,会调用 FetchPlayers() 来获取将显示的玩家列表。用户还可以通过菜单编辑这些球员信息。当用户确认编辑(通过按钮按下)时,应用程序首先调用 EditPlayer(),然后在调用 FetchPlayers() 之后的行中更新网页上的播放器列表。

问题是页面没有使用新的编辑进行更新。对我来说,查看新编辑我必须重新加载页面。这表明 FetchPlayers() 在 EditPlayer() 之前以某种方式被调用。有谁知道我该如何解决这个问题?

提前致谢!

编辑

edit_player(_playerid, _newfirstname, _newlastname, _newclass) {
    fetch('http://' + Globals.BaseIP + Globals.PortForBackend + '/api/editplayer', {
        //Options for the fetch request
        method:'POST',
        headers: {
            //Header objects
            'Accept':'application/json, text/plain, */*',
            'Content-type':'application/json'
        },
        body:JSON.stringify({UserID:UserServiceLocal.UserID(), token:UserServiceLocal.token(), GameID:this.props.gameID, PlayerID:_playerid, Firstname:_newfirstname, Lastname:_newlastname, Class:_newclass}),
        mode:'cors'
    })
    .catch((error) => console.log(error));


}

FetchPlayers 代码

FetchPlayers () {
    fetch('http://' + Globals.BaseIP + Globals.PortForBackend + '/api/fetchplayers', {
        //Options for the fetch request
        method:'POST',
        headers: {
            //Header objects
            'Accept':'application/json, text/plain, */*',
            'Content-type':'application/json'
        },
        body:JSON.stringify({UserID:UserServiceLocal.UserID(), token:UserServiceLocal.token(), GameID:this.props.gameID}),
        mode:'cors'
    })
    .then((res) => res.json())
    .then((data) => this.parse_fetch_players_response(data))
    .catch((error) => console.log(error))
}


parse_fetch_players_response(data) {
    console.log(data['players']);
    this.setState({Playerlist:data['players']});
    this.ListScrollToBottom();
}

确认编辑时运行的代码

Btn_EditPlayer() {
    this.edit_player(this.state.playereditID, this.state.playereditName, 
    this.state.playereditLastname, this.state.playereditClass);
    this.FetchPlayers();

渲染函数:

return (
                <div className="PageFooter" onKeyPress={(event) => this.EnterKeyPress_EditPlayer(event)}>
                    <Textinput className="FirstNameTextbox" id="playereditName" label="First name" value={this.state.playereditName} onChange={this.textinput_handleChange}/>
                    <Textinput className="LastNameTextbox" id="playereditLastname" label="Last name" value={this.state.playereditLastname} onChange={this.textinput_handleChange}/>
                    <Textinput className="ClassTextbox" id="playereditClass" label="Class" value={this.state.playereditClass} onChange={this.textinput_handleChange}/>
                    <button id='editPlayerButton' className="mdc-button mdc-button--unelevated mdl-button--colored mdc-ripple-surface" onClick={() => this.Btn_EditPlayer()}>Edit Player</button>
                    <button id="cancel-edit-player-btn" className="mdc-button mdc-button--raised mdl-button--colored mdc-ripple-surface" onClick={() => this.EditPlayer_Cancel_Btn()}>Cancel</button>
                </div>
            );

列表元素渲染功能:

return (
            <div>
                <ul className="mdc-list" id="list-container" >

                    <li role="separator" className="mdc-list-divider"></li>

                    <li className="mdc-list-item" >
                        <span className="mdc-list-item__text list_text_firstname">
                            <b>Firstname</b>
                        </span>

                        <span className="mdc-list-item__text list_text_lastname">
                            <b>Lastname</b>
                        </span>

                        <span className="mdc-list-item__text list_text_class">
                            <b>Class</b>
                        </span>

                        <span className="mdc-list-item__graphic" role="presentation">
                            <i className="material-icons list_edit_icon">edit</i>
                            <i className="material-icons list_remove_icon">delete</i>

                        </span>
                    </li>
                    <li role="separator" className="mdc-list-divider"></li>

                    <ListEntry ListItemCSS="selected-list-entry" firstname="This is above" lastname="Butter" class="Jelly" id="1" delete_self={(playerID) => this.delete_item(playerID)} edit_button_clicked={(playerID) => this.Edit_Button_Clicked(playerID)}/>
                    <ListEntry firstname="Peanut" lastname="Butter" class="Jelly" id="1" delete_self={(playerID) => this.delete_item(playerID)} edit_button_clicked={(playerID) => this.Edit_Button_Clicked(playerID)}/>




                        {playerListItems}


                    </ul>
            </div>

            );

【问题讨论】:

  • 请提供您的代码a minimal, complete, and verifiable example。没有它,你的代码可能出了什么问题,这只是一场猜谜游戏。
  • 你可以让 FetchPlayers 回调到 EditPlayer,这样 FetchPlayers 只在 EditPlayers 回来后运行吗?另外,我们可以看看你的代码吗?
  • @trixn 好的,我会补充的!
  • @MichaelSorensen 我该如何回电?
  • @Ben10 在此处查看此示例:developer.mozilla.org/en-US/docs/Glossary/Callback_function(要明确,这可能不是您问题的解决方案)

标签: javascript reactjs fetch


【解决方案1】:

尝试从Btn_EditPlayer() 中删除this.FetchPlayers() 并将其添加为edit_player 的回调,如下所示:

this.edit_player(this.state.playereditID, this.state.playereditName, 
    this.state.playereditLastname, this.state.playereditClass, this.FetchPlayers);

edit_player(_playerid, _newfirstname, _newlastname, _newclass, callBack) {
    fetch('http://' + Globals.BaseIP + Globals.PortForBackend + '/api/editplayer', {
        //Options for the fetch request
        method:'POST',
        headers: {
            //Header objects
            'Accept':'application/json, text/plain, */*',
            'Content-type':'application/json'
        },
        body:JSON.stringify({UserID:UserServiceLocal.UserID(), token:UserServiceLocal.token(), GameID:this.props.gameID, PlayerID:_playerid, Firstname:_newfirstname, Lastname:_newlastname, Class:_newclass}),
        mode:'cors'
    }).then((res) => {
        // run your callback (fetchPlayers in this case) only when we know the update is done.
       callBack()
    }).catch((error) => console.log(error));
}

编辑(错字)

【讨论】:

  • 我添加了这个,有趣的是this.FetchPlayers() 正在运行(因为console.log)输出。但是它不会改变页面的状态
  • 您是否至少获得了更新的数据,而不是之前的球员数据集?此外,查看您的渲染功能,该组件似乎只处理一个玩家而不是所有玩家。你只是想更新页面上的那个单人游戏吗?如果你是,你应该能够从你的 POST 请求传回更新的玩家信息,并一起跳过辅助 GET 请求。
  • 我从 fetchplayers() 打印出数据,这是数据库正在更新。只是状态没有改变。
  • 对于列表,我使用 .map() 函数遍历玩家数组(处于状态)并显示 &lt;li&gt; 元素。是的,它用于编辑其中一名球员
  • 您在组件生命周期的哪个部分生成这些
  • 元素?如果不是太麻烦,请使用整个组件更新您的帖子。
【解决方案2】:

不看代码是不可能知道的,但通常问题是你没有将信息存储在 state 中,或者你的 JSX 在渲染返回中没有使用 this.state 的属性所以它不知道重新渲染。

【讨论】:

  • 你的渲染函数是什么样的?
  • 当用户单击按钮确认他们要提交所做的编辑时,此代码将运行。我现在已经添加了该代码
  • 我仍然没有看到渲染功能。什么是 JSX?不明白的就贴出所有的组件代码吧。
  • 这里和那里的小块真的很难解析出来。我注意到的一件事:
  • parse_fetch_players_response(data) { console.log(data['players']); this.setState({Playerlist:data['players']}); this.ListScrollToBottom(); }
猜你喜欢
相关资源
最近更新 更多
热门标签