如何从反应中获取的json数据中异常记录一个对象?

时间:2017-08-30 07:42:58

标签: reactjs

有没有办法记录1个对象或2个或者我想要登录控制台的次数?
我使用来自jsonplaceholder.typicode.com的简单数据(非常有用于学习目的),每个对象都有唯一的id。
例如:
我在网站上获取数据并呈现了200个帖子,好吧......但是如果我有一个包含100个徽标或横幅或网站布局的数据我想要呈现具有唯一ID 30的特定徽标或横幅。 那么,我怎样才能只渲染200个第1,第2,第3或第x个帖子/帖子?

这就是我现在拥有的: App.js

import React, { Component } from 'react';
import './css/App.css';
import './css/bootstrap.css';
import $ from 'jquery';
import Todos from './Todos';

class App extends Component {
    constructor(props) {
        super(props);

        this.state={
            todos:[],
        };
      }

      getTodos() {
        $.ajax({
            url: 'https://jsonplaceholder.typicode.com/todos',
            dataType: 'json',
            cache: false,
            success: function (data) {
                this.setState({todos: data}, function () {
                    console.log(this.state);
                });
            }.bind(this),
            error: function (xhr, status, err) {
                console.log(err);
            }
        })
      }
      componentWillMount(){
        this.getTodos();
      }
      componentDidMount() {
        this.getTodos();
      }
      
      render() {
      return (
      <div>
        <Todos todos={this.state.todos}/>
      </div>
    );
  }
}

export default App;

Todos.js

import React, {Component} from 'react';
import TodoItem from './TodoItem';

class Todos extends Component {
    render() {
        let todoItems;
        if(this.props.todos) {
            todoItems = this.props.todos.map(todo => {
                return (
                    <TodoItem key={todo.title} todo = {todo} />
                );
            });
        }
        return (
            <div>
                <h2>Todo list from api</h2>
                {todoItems}
            </div>
        );
    }
}

Todos.propTypes = {
    todos: React.PropTypes.array
};

export default Todos;

TodoItem.js

import React, {Component} from 'react';

class TodoItem extends Component {
    render() {
        return (
            <li>
                <strong>{this.props.todo.title}</strong>
            </li>
        );
    }
}
TodoItem.propTypes = {
    todo: React.PropTypes.object
};
export default TodoItem;

@edit 是否有可能过滤映射的json数据并根据id查找对象然后呈现此对象?

2 个答案:

答案 0 :(得分:2)

切片多个项目

您可以使用其他状态属性,例如 filterCount ,可以手动设置,也可以从按钮触发 setState 事件,例如

constructor(props) {
    super(props);

    this.setFilter = this.setFilter.bind(this);
    this.state={
        todos: [],
        filterCount: 20 // Default value
    };
}

setFilter(count) {
    this.setState({ filterCount: count });
}

render() {
    const { todos, filterCount } = this.state;

    return(
        <div>
            ...
            <button onClick={this.setFilter(10)} />
            <button onClick={this.setFilter(20)} />
            <button onClick={this.setFilter(50)} />
        </div>
    )
}

这将确保每次更改计数时都会重新呈现您的组件。

现在是第二部分,过滤前x个项目。

主要方法是使用Array.prototype.slice

切片示例:

render() {
    const { todos, filterCount } = this.state;
    const filteredToDos = todos.slice(0,filterCount);

    return(
        <div>
            ...
            { filteredToDos.map(todo => {
                return (
                    <TodoItem key={todo.title} todo={todo} />
                );
            }) }
        </div>
    )
}

请确保您不会意外地使用拼接而不是 slice ,因为splice不会复制到新数组,而是修改原始数组。< / p>

可以轻松修改此示例以支持分页。您可以将 currentPage 参数添加到状态,只需修改切片线以根据您所在的页面切割数组。

此外,请仔细考虑是否需要在应用中使用jQuery。如果你只是为了方便而使用它,那么你犯了一个大错误,因为它是一个巨大的库,可以大大增加你的包大小。尝试以反应的方式学习做事:)

您的ajax请求可以使用 fetch api。

完成
return fetch("https://jsonplaceholder.typicode.com/todos")
        .then(response => response.json())
        .catch((error) => {
            console.error(error);
        });

如果您不需要为旧浏览器提供开箱即用的支持,那么对于现有浏览器的最后2-3个主要版本(包括移动浏览器),fetch api将会很好。它可以用于IE8之类的旧版本。

此外,如果您需要更多选项并支持所有请求类型和标头,那么像 axios 这样的库实际上比jQuery小得多。

此外,fetch操作本身可以从组件分离到单独的 actions.js 文件,以便将来可以从多个组件导入/使用,或者更容易重构以支持如果您的应用程序增长,请使用Redux之类的东西。

获取单个项目

直接从API获取单项 - 建议

如果我们谈论性能,那么最好的方法是直接从API获取单个项目。考虑到这是一个基于REST的api,那么方式将是:

https://jsonplaceholder.typicode.com/todos/ {ID}

使用模板文字重写获取示例:

return fetch(`https://jsonplaceholder.typicode.com/todos/${itemId}`)
        .then(response => response.json())
        .catch((error) => {
            console.error(error);
        });

这也应该返回单个对象,而不是数组,因此您应该能够将其作为道具传递并立即使用它。恕我直言,这是解决问题的最佳方法。


从API获取所有项目,然后使用过滤器

进行过滤

第二个选项是获取所有布局,然后过滤您在以下示例中看到的结果:@ mayank-shukla

此方法的瓶颈是Array.prototype.filter可以返回多个结果。


从API获取所有项目,然后使用find

进行过滤

第三个选项是获取所有布局,然后使用Array.prototype.find

过滤结果

示例与过滤器相同,只需将关键字更改为查找。

如果有多个结果,查找将返回第一个结果。


从API获取所有项目,然后按索引过滤

第四个选项是获取所有布局,然后按索引过滤,例如

todos[itemId-1]

这也可以,但是,您需要100%确定后端是否会按照其ID在数组中排序结果。此外,索引从0开始,你的id从1开始,所以这可能是一个主要混乱的来源。

答案 1 :(得分:1)

而不是将所有数据传递给子组件,而不是根据条件过滤出数据,并将过滤后的数据传递给子组件。

像这样:

render() {
    //filter data of these ids
    let ids = [1,2,3,4];

    //filtered data
    let data = this.state.todos.filter(el => ids.indexOf(el.id) != -1);

    return (
        <div>
            <Todos todos={data}/>
        </div>
    );
}

如果要传递前x个数据,请使用#array.slice并传递结果,如下所示:

render() {
    //filtered data
    let data = this.state.todos.slice(0, 20);

    return (
        <div>
            <Todos todos={data}/>
        </div>
    );
}

您可以在获得响应后执行此操作,而不是将过滤器部件放在渲染中。