React JS将项目推送到数组以获取列表

Posted

技术标签:

【中文标题】React JS将项目推送到数组以获取列表【英文标题】:React JS Pushing Items to Array for List 【发布时间】:2017-03-17 18:03:03 【问题描述】:

我仍然习惯于做出反应,但似乎遇到了一个问题,即我无法将数组项作为文本而不是对象推送。现在,我有一个 API 调用来检索 json,然后将其存储到一个状态以供以后使用。最终目标是在 return 语句中生成一个无序列表,但是,每当我尝试将项目推送到我的数组时,它们都会以对象而不是字符串的形式出现。我该如何解决这个问题?

状态和 API 调用

class App extends Component 
    constructor(props) 
        super(props);
        this.state = 
            value: '',
            data: , //filled by fetch data from API
            imgData: , //filled by fetch image data from API
            typeData: , //filled by fetch types data from API
            types: 
                typesArray: []
            ,
            typeDataTotal: ,
            specificTypeData: 
        ;
    

    handleChange(event) 
        this.setState(value: event.target.value);
    

    handleSubmit(event) 
        //alert('Text field value is: ' + this.state.value);
        var _this = this;
        fetch('https://pokeapi.co/api/v2/pokemon/' + this.state.value + '/').then(function(response) 
            if (response.status !== 200) 
                console.log('Looks like there was a problem. Status Code: ' + response.status);
                return;
            
            // Examine the text in the response
            response.json().then(function(data) 
                console.log(data);
                console.log(data.sprites.front_default);
                _this.setState(data: data);
                _this.setState(imgData: data.sprites);
                _this.setState(typeData: data.types[0].type);
                _this.setState(specificTypeData: data.types); //this is the one I want to use for keys in the array
                _this.setState(
                    typeDataTotal: Object.keys(data.types)
                );
                console.log(data.types[0].type.name); //shows item as string
                console.log(data.types[1].type.name);
                console.log(Object.keys(data.types).length);

            );
        
    

    render() 
        var data = this.state.data;
        var imgData = this.state.imgData;
        var typeData = this.state.typeData;
        var typeDataTotal = this.state.typeDataTotal;
        var specificTypeData = this.state.specificTypeData;
        var forms = [];

        for (var key in typeDataTotal) 
            console.log("obj." + key + " = " + specificTypeData[key].type.name);
            forms.push(<formjs data=specificTypeData[key].type.name/>);
            console.log(forms);
        
        return (
            <div>forms</div>
        );

    

输出示例:

【问题讨论】:

【参考方案1】:

typeDataTotal 是一个对象,您正在尝试使用for 循环对其进行迭代并检查它的length 属性。简单对象,例如您分配给typeDataTotal 的对象没有length 属性,因此您的i &lt; typeDataTotal.length 条件立即为假,因此循环到此结束。

为了遍历简单对象,请使用 for &lt;key&gt; in &lt;object&gt; 循环

更新1:

让我们检查一下您的状态对象及其属性:

this.state = 
        value: '',
        data: , //filled by fetch data from API
        imgData: , //filled by fetch image data from API
        typeData: , //filled by fetch types data from API
        types: 
            typesArray: []
        ,
        typeDataTotal: ,
        specificTypeData: 
    ;

我们在这里看到:

this.state.valuestringthis.state.dataobject this.state.imgDataobject this.state.typeDataobject this.state.typesobject this.state.types.typesArrayarray this.state.typeDataTotalobject this.state.specificTypeDataobject

考虑到这些:

_this.setState(specificTypeData: data.types); //this is the one I want to use for keys in the array

这可能是错误的。从上面的操作来看,当您执行_this.setState(typeData: data.types[0].type); 时,您会让我明白data.typesarrayspecificTypeData 应该是 object,所以在这里您只需将 specificTypeData 更改为指向 array 而不是 object。由于您在创建状态时将specificTypeData 设置为object,因此它应该始终保持为object

如果data.types不是 数组,那么您通过data.types[0] 访问它的值是错误的。如果它是一个数组,而不是一个对象,这就是访问它的元素的方式。

_this.setState(
    typeDataTotal: Object.keys(data.types)
);

在这里你让我明白data.types 实际上是一个对象,所以很可能,你在上一行中访问它的属性是错误的。

console.log(data.types[0].type.name); //shows item as string
console.log(data.types[1].type.name);

再次,data.types 是什么?是object 还是array

更新2:

忘记在上面提到了,当你这样做时

_this.setState(
    typeDataTotal: Object.keys(data.types)
);

您将typeDataTotal 更改为array,而您最初将其定义为object。决定 typeDataTotal 应该是什么(例如,当你初始化 state 时,你可以将它设置为一个数组,如果它比 object 更有意义)并给它一个适当的值。

所以,既然我们现在知道 data.types 是一个对象,那么在您运行 response.json().then() 回调中的代码后,您的状态如下所示。

你这样做:

_this.setState(data: data);
_this.setState(imgData: data.sprites);
_this.setState(typeData: data.types[0].type);
_this.setState(specificTypeData: data.types); //this is the one I want to use for keys in the array
_this.setState(
    typeDataTotal: Object.keys(data.types)
);

所以你最终会得到这个状态:

this.state = 
    value: <string>, //this was unmodified
    data: data,  //it's an <object>, should be an <object>
    imgData: data.sprites, //I don't know what data.sprites is but should be an <object>
    typeData: data.types[0].type, //It's <undefined>, should be an <object>
    types: 
        typesArray: <array> //this was unmodified
    ,
    typeDataTotal: Object.keys(data.types), //It's an <array>, should be an <object>
    specificTypeData: data.types //it's an <object>, should be an <object>
;

所以,我们终于找到了你的render 方法,让我们看看这个状态会发生什么:

render() 
    var data = this.state.data; //it's an <object>, should be an <object>
    var imgData = this.state.imgData; //I don't know what data.sprites is but should be an <object>
    var typeData = this.state.typeData; //It's <undefined>, should be an <object>
    var typeDataTotal = this.state.typeDataTotal; //It's an <array>, should be an <object>
    var specificTypeData = this.state.specificTypeData; //it's an <object>, should be an <object>
    var forms = [];

    for (var key in typeDataTotal)  // you are now iterating over an array, so key is an integer number (0, 1, 2, etc)
        console.log("obj." + key + " = " + specificTypeData[key].type.name); //specificTypeData is an object, and you are trying to access its values by doing specificTypeData[<number>] which will return undefined.
        forms.push(<formjs data=specificTypeData[key].type.name/>); //data=undefined
        console.log(forms);
    
    return (
        <div>forms</div>
    );

如果我在你的位置,我会做如下:

转动这些:

_this.setState(data: data);
_this.setState(imgData: data.sprites);
_this.setState(typeData: data.types[0].type);
_this.setState(specificTypeData: data.types); //this is the one I want to use for keys in the array
_this.setState(
    typeDataTotal: Object.keys(data.types)
);

进入

_this.setState(
    data: data,
    imgData: data.sprites,
    typeData: <object>,
    specificTypeData: data.types,
    typeDataTotal: <whatever you decide>
);

我认为 react 是将你所有的 _this.setState() 调用合并为一个,这样你无论如何只会触发一次 render,但这样做是为了确保。

并且肯定重新考虑应该如何表示您的状态;什么应该是object,什么应该是array

你最终会解决这个问题的。

【讨论】:

我已将我的代码更新为最新版本。当我 console.log 对象/键对时,它们显示为字符串。但是,当我尝试将其推入表单数组时,它会返回到 [Object, Object]。 抱歉,我刚刚注意到,但是,您的 returning 在您的 render 方法中到底是什么?你应该在那里返回一些东西 我要返回 forms 能否更新您问题中的代码以反映您正在使用的代码并遇到问题? 那么,例如,当您执行console.log("obj." + key + " = " + specificTypeData[key].type.name); 时,它会打印John?你能在你的问题中分享你的&lt;formjs&gt; 组件的实现吗?

以上是关于React JS将项目推送到数组以获取列表的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Promises:异步推送到数组并保存

将所有数据推送到数组后设置状态

Javascript/jQuery - 将项目推送到数组并从数组中删除

Vuex store - 将状态中的项目推送到状态数组导致数组中的前一个项目更改为当前状态项目

Angular 4 - 从可观察到的将新项目推送到数组

使用Angular2中的接口将对象推送到新数组中