反应“获取”响应成功,但setState不起作用

时间:2018-10-23 12:50:09

标签: reactjs

我是React的新手,正在完成“ .Net core CRUD with React”教程,并尝试根据自己的需要进行调整。

我正在处理的页面是“添加/编辑”输入页面。对于呈现具有默认值的默认表单,它工作得很好,但是如果这些值是从fetch调用中收集的,则不会呈现任何内容。

重要细节如下:

interface AddPortfolioProjectDataState {
    title: string;
    projectData: PortfolioProject;
    loading: boolean;
}

告知页面呈现如下:

public render() {
    let contents = this.state.loading
        ? <p><em>Loading Project...</em></p>
        : this.renderCreateForm(this.state.projectData.type, this.state.projectData.tech);

    return (
        <div>
            <h1>{this.state.title}</h1>
            <h3>Project</h3>
            <hr />
            {contents}
        </div>
        )
}

如果我要添加新项目,因此使用具有默认值的默认PortfolioProject对象,它可以正常工作。但是,如果要编辑旧条目,则必须从服务器上抓取它,如下所示:

fetch('api/StuartAitkenWebsite/GetPortfolioProject/' + projID)
                .then(response => response.json() as Promise<PortfolioProject>)
                .then(data => {
                    this.setState({ title: "Edit", loading: false, projectData: data });
                }); 

在Firefox的调试控制台中,我可以看到整个服务器进程运行顺利:

GET http://localhost:62669/api/StuartAitkenWebsite/GetPortfolioProject/2

Response payload: {"id":2,"name":"Particles Sim","projectDate":"2017-01-01T00:00:00","projectDurationWeeks":1,"type":"Desktop App","tech":"C++, SFML","views":0,"creationDate":"2018-10-22T00:00:00","modifiedDate":"2018-10-22T00:00:00","status":1}`

它也提供了有效负载的JSON输出,在这里我不能轻易地将其粘贴粘贴,因此我将给出一个屏幕截图:

enter image description here

没有服务器错误响应,没有React错误,什么都没有。

但那已经尽了。

即使数据已经准备好并希望显示,页面仍显示“正在加载”。

由此,我可以了解到,由于this.setState({ title: "Edit", loading: false, projectData: data });显然对页面数据没有任何影响,因此fetch调用的最后一步没有成功。

我还有其他访存调用,它们看起来完全一样,但工作正常。我看不到我在这里想念的东西。

我注意到的唯一的区别是:

当我使用此组件创建新的“添加项目”表单时,状态设置如下:

this.state = {
            title: "Create",
            loading: false,
            projectData: new PortfolioProject,
        };

但是当我通过API执行此操作时,它的设置如下:

this.setState({
                    title: "Edit",
                    loading: false,
                    projectData: data
                });

成功的版本使用this.state,而失败的版本使用this.setState

我不知道这意味着什么。正如我所说,不会引发任何错误,我坚持使用教程格式,并且在项目的其他部分也能正常工作。

谢谢。

更新

我已经在调用renderCreateForm()的位置登录了。看来setState实际上在工作。因此,问题必须出在renderCreateForm()中,因此我将在下面发布该代码。抱歉,它有点大。

private renderCreateForm(projectTypes: string, projectTech: string) {

    console.log(this.state.loading); // "false"
    console.log(this.state.projectData); //"Object { id:1, name: "Muon Detector".. etc 
//so the render is getting the data


    return (
        <form onSubmit={this.handleSave}>
            <div className="form-group row" >
                <input type="hidden" name="Id" value={this.state.projectData.id} />
            </div>  
            <div className="form-group row" >
                <label className=" control-label col-md-12" htmlFor="Name">Name</label>
                <div className="col-md-4">
                    <input className="form-control" type="text" name="Name" defaultValue={this.state.projectData.name} required />
                </div>
            </div>
            <div className="form-group row" >
                <label className=" control-label col-md-12" htmlFor="ProjectDate">Project Date</label>
                <div className="col-md-4">

                    <input className="form-control" type="date" name="ProjectDate" defaultValue={this.state.projectData.creationDate.toDateString()} required />
                </div>
            </div >  
            <div className="form-group row" >
                <label className=" control-label col-md-12" htmlFor="ProjectDurationWeeks">Project Duration (weeks)</label>
                <div className="col-md-4">
                    <input className="form-control" type="text" name="ProjectDurationWeeks" defaultValue={this.state.projectData.projectDurationWeeks.toString()} required />
                </div>
            </div >  
            <div className="form-group row" >
                <label className=" control-label col-md-12" htmlFor="Type">Project Type</label>
                <div className="col-md-4">
                    <input className="form-control" type="text" name="Type" defaultValue={this.state.projectData.type} required />
                </div>
            </div >
            <div className="form-group row" >
                <label className=" control-label col-md-12" htmlFor="Tech">Project Tech</label>
                <div className="col-md-4">
                    <input className="form-control" type="text" name="Tech" defaultValue={this.state.projectData.tech} required />
                </div>
            </div >
            <div className="form-group row" >
                <input type="hidden" name="Views" value={this.state.projectData.views} />
            </div>  
            <div className="form-group row" >
                <input type="hidden" name="CreationDate" value={this.state.projectData.creationDate.toDateString()} />
            </div>  
            <div className="form-group row" >
                <input type="hidden" name="ModifiedDate" value={this.state.projectData.modifiedDate.toDateString()} />
            </div>  
            <div className="form-group row" >
                <input type="hidden" name="Status" value={this.state.projectData.status} />
            </div>  
            <div className="form-group">
                <button type="submit" className="btn btn-default">Save</button>
                <button className="btn" onClick={this.handleCancel}>Cancel</button>
            </div >  
        </form>
        )
}

更新2 :添加了一些屏幕快照,显示了到目前为止的情况。

  1. 主数据表页面的外观:

enter image description here

  1. 如果我点击“添加新内容”,它会起作用:

enter image description here

(“保存”选项也可以在这里使用。数据会发布到服务器上,并会在主要投资组合页面上列出)

  1. 对于任何条目单击“编辑”均不起作用,它可以解决以下问题:

enter image description here

正在加载项目... ”文本来自此页面的render()调用,如本文顶部的代码所示。

该页面看起来应该与“创建”页面(第二张屏幕截图)完全一样,但标题为“编辑”,并使用给定数据填充输入值。

1 个答案:

答案 0 :(得分:0)

解决方案很荒谬,但肯定可以帮助其他人...

由于我在一些输入中使用了renderCreateForm()方法,.toDateString()方法(如帖子的更新1所示)无法正常工作。

我将其更改为.toString(),现在一切正常。

例如,使用这样的输入:

<input className="form-control" type="date" name="ProjectDate" defaultValue={projectData.creationDate.toDateString()} required />

我将其更改为此:

<input className="form-control" type="date" name="ProjectDate" defaultValue={projectData.creationDate.toString()} required />

请注意输入的defaultValue属性。

针对所有.ToDateString()重复,现在可以使用

令人惊讶的是,这并没有在任何地方引发错误。我认为Typescript和所有这些各种框架都应该能够解决Javascript这样的无声失败的问题。这是我有史以来最长,最浪费时间的“静音失败错误”。