0

我有一个 fetch api 调用,它返回一个非常大的数组,其中包含书籍和相关信息,我只需要标题、作者和相关段落。在componentDidMount()我试图抓住这些值,并将它们推入一个新数组中,以对我的项目有意义的方式构造。

我成功地抓取并推送了这些值,但我无法维护嵌套结构。我希望书名和作者在顶部,然后将段落放在与书关联的嵌套数组中。我当前的代码只是将所有内容推到同一级别,没有嵌套。

在下面的代码中,我基本上想要this.state.dummyBooks并且this.state.booksStructured是相同的。

jsfiddle

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            dummyBooks: [
                {
                    title: "book title one",
                    author: "book author one",
                    passages: [
                        {
                            id: 1,
                            passage: "this is a passage",
                        },
                        {
                            id: 2,
                            passage: "this is another passage",
                        },
                    ],
                },
                {
                    title: "book title two",
                    author: "book author two",
                    passages: [
                        {
                            id: 3,
                            passage: "this is a third passage",
                        },
                        {
                            id: 4,
                            passage: "this is yet another passage",
                        },
                    ],
                },
            ],
            booksStructured: [],
        };
    }

    componentDidMount() {
        this.state.dummyBooks.map(bookObject => {
            this.state.booksStructured.push({
                bookTitle: bookObject.title,
                bookAuthor: bookObject.author,
            });

            bookObject.passages.map(passageObject => {
                this.state.booksStructured.push({
                    passageID: passageObject.id,
                    passageText: passageObject.passage,
                });
            });
        });
    }

    render() {
        console.log(this.state.booksStructured);
        return <div>check the console</div>;
    }
}

ReactDOM.render(<App />, document.querySelector("#app"));

4

4 回答 4

0

只需从中获取所需的密钥this.state.dummyBooks并将其推到this.state.booksStructured

componentDidMount() {
    for(const {title, author, passages} of this.state.dummyBooks){
        this.state.booksStructured.push({title:title,author:author,passages:passages});
    }
}
于 2020-02-27T19:40:57.230 回答
0

与其尝试设置this.state.booksStructured为循环this.state.dummyBooks,不如根据 中的映射值创建一个数组this.state.dummyBooks,创建变量并相应地分配更新的键/值对。完成后用于this.setState({...})将新数组分配给this.state.booksStructured.

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        dummyBooks: [
            {
            'title': 'book title one',
          'author': 'book author one',
          'passages': [
            {
                'id': 1,
                'passage': 'this is a passage'
            }, {
                'id': 2,
              'passage': 'this is another passage'
            }
          ]
        }, {
            'title': 'book title two',
          'author': 'book author two',
          'passages': [
            {
                'id': 3,
                'passage': 'this is a thridpassage'
            }, {
                'id': 4,
              'passage': 'this is yet another passage'
            }
          ]
        }   
        ],
      booksStructured: [],
    }

  }

    componentDidMount() {
    var booksStructured = this.state.dummyBooks.map(bookObject => {
    var obj = {}
    var {title, author, passages} = bookObject

    obj['bookTitle'] = title
    obj['bookAuthor'] = author

      passages = passages.map(x=>{
        var passageObj = {}
        passageObj['passageID'] = x.id
        passageObj['passageText'] = x.passage  
        return passageObj
      });

    obj['passages'] = passages
    return obj
    })

  this.setState({
    booksStructured
  })
  }

  render() {
    console.log(this.state.booksStructured);
    return (
      <div>
        check the console
      </div>
    )
  }
}

ReactDOM.render(<App />, document.querySelector("#app"))

在这里查看。

于 2020-02-27T19:42:03.270 回答
0

如果您仔细查看componentDidMount方法中的代码,您应该注意到您实际上在做的是迭代dummyBooks并将仅包含书籍作者和标题booksStructured的对象推送到数组中,然后将仅包含段落 id 和文本的对象推送到数组中booksStructured数组。因此,生成的交替书和段落对象数组。

booksStructured相反,您可能希望在将其推入数组之前创建一个包含书籍和段落信息的对象。您也不应该建议使用它来setState()支持this.state.push()

永远不要直接改变 this.state,因为之后调用 setState() 可能会替换你所做的改变。将 this.state 视为不可变的。文档

而且您通常不应该setState()循环调用,因为

setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用 setState() 之后立即读取 this.state 是一个潜在的陷阱。文档

考虑到这一点,您的解决方案应如下所示:

componentDidMount() {
  const structuredBooks = [];

  this.state.dummyBooks.map(bookObject => {
    // Iterate over each passage, returning a new object with only
    // the wanted fields from each passage object
    const structuredPasssages = bookObject.passages.map(passage => {
      passageID: passageObject.id,
      passageText: passageObject.passage,
    });

    // Construct a structured book object using the new passages
    const structuredBook = {
      bookTitle: bookObject.title,
      bookAuthor: bookObject.author,
      passages: structuredPassages,
    };

    // Push the structured book into "structuredBooks"
    structuredBooks.push(structuredBook);
  });

  // Update state with the complete structuredBooks array
  this.setState({ booksStructured: structuredBooks });
}
于 2020-02-27T20:08:33.757 回答
0

使用 map 循环遍历对象并返回所需的结构。

const booksStructured = apiData.map(book => {
  return {
    title: book.title,
    author: book.author,
    passages: book.passages
  };
});

请不要直接修改状态变量,比如

this.state.booksStructured.push({ title:title,author:author, passages:passages});

将值保存在局部变量中并使用更新状态.setState()

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>

<script>

const apiData = [
  {
    title: 'book title one',
    author: 'book author one',
    more: 'more',
    xtra: 'tets',
    year: 2030,
    passages: [
      {
        id: 1,
        passage: 'this is a passage',
      },
      {
        id: 2,
        passage: 'this is another passage',
      },
    ],
  },
  {
    title: 'book title two',
    author: 'book author two',
    more: 'more',
    xtra: 'tets',
    year: 2000,
    passages: [
      {
        id: 1,
        passage: 'this is a passage',
      },
      {
        id: 2,
        passage: 'this is another passage',
      },
    ],
  },
  {
    title: 'book title three',
    author: 'book author three',
    more: 'more',
    xtra: 'tets',
    year: 2001,
    passages: [
      {
        id: 1,
        passage: 'this is a passage',
      },
      {
        id: 2,
        passage: 'this is another passage',
      },
    ],
  },
];
  
</script>

<script type="text/babel">

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "React",
      dummyBooks: [
        {
          title: "book title one",
          author: "book author one",
          passages: [
            {
              id: 1,
              passage: "this is a passage"
            },
            {
              id: 2,
              passage: "this is another passage"
            }
          ]
        },
        {
          title: "book title two",
          author: "book author two",
          passages: [
            {
              id: 3,
              passage: "this is a third passage"
            },
            {
              id: 4,
              passage: "this is yet another passage"
            }
          ]
        }
      ],
      booksStructured: []
    };
  }

  componentDidMount = () => {
    const booksStructured = apiData.map(book => {
      return {
        title: book.title,
        author: book.author,
        passages: book.passages
      };
    });

    this.setState({
      booksStructured: booksStructured
    });
  };

  render() {
    console.log(this.state.booksStructured);
    return <div>check the console</div>;
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
</script>

于 2020-02-27T20:10:20.753 回答