如何在React.js前端应用程序中显示来自Rails 5 API的数据?

时间:2018-11-06 06:24:56

标签: javascript ruby-on-rails json reactjs rails-api

我已经用Rails建立了一个API,其中一个http://localhost:3001/api/words端点公开了以下数据:

[{"id":1,"term":"Reach","definition":"Reach is the number of people who had any content from your Page or about your Page enter their screen.","example":"","author":"Loomly","credit":"https://www.loomly.com/","created_at":"2018-11-02T03:21:20.718Z","updated_at":"2018-11-02T03:21:20.718Z"},{"id":2,"term":"Emoji","definition":"A small digital image or icon used to express an idea, emotion, etc., in electronic communication","example":"","author":"Loomly","credit":"https://www.loomly.com/","created_at":"2018-11-02T03:23:50.595Z","updated_at":"2018-11-02T03:23:50.595Z"}]

我现在正试图在使用Create React App构建的React.js前端应用程序中简单地显示此数据(理想情况下为无序列表),这是我的App.js文件的内容:

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

class App extends Component {
  constructor () {
    super()
    this.state = {}
    this.getWords = this.getWords.bind(this)
    this.getWord = this.getWord.bind(this)
  }

  componentDidMount () {
    this.getWords()
  }

  fetch (endpoint) {
    return window.fetch(endpoint)
      .then(response => response.json())
      .catch(error => console.log(error))
  }

  getWords () {
    this.fetch('/api/words')
      .then(words => {
        if (words.length) {
          this.setState({words: words})
          this.getWord(words[0].id)
        } else {
          this.setState({words: []})
        }
      })
  }

  getWord (id) {
    this.fetch(`/api/words/${id}`)
      .then(word => this.setState({word: word}))
  }

  render () {
    let {words, word} = this.state
    return (
      <div>
        {Object.keys(words).map((key) => {
          return (
            <div key={word.id}>
              <p>{word.term}</p>;
            </div>
          )
        })}
      </div>
    )
  }
}

export default App;

我认为问题出在代码的以下区域:

render () {
  let {words, word} = this.state
    return (
      <div>
        {Object.keys(words).map((key) => {
          return (
            <div key={word.id}>
              <p>{word.term}</p>;
            </div>
          )
        })}
      </div>
    )
}

我尝试遵循this tutorialthat other tutorial中解释的步骤,同时保持页面的布局尽可能简单(semantic-ui-css中没有喧嚣),无论我尝试什么,我都会不断遇到以下错误:

  • TypeError: Cannot convert undefined or null to object
  • Unexpected token, expected “,”
  • Failed to compile: 'word' is not defined no-undef

this article中解释的解决方案使我想到了我现在拥有的代码,但是在构建React应用程序的方式上我缺少一些东西:你能指出正确的方向吗?

3 个答案:

答案 0 :(得分:2)

getWords () {    
  fetch('http://localhost:3001/api/words')
  .then((response) => {
    return response.json();
  })
  .then((res) => {
    // console.log(res); you should get the response you mentioned
    this.setState({words: res});
  });
}

然后检查您是否通过安慰使数据处于您的状态。

然后您可以使用以下内容进行处理

render{
 return(
   <div>
     { this.state.words.map((val) => (
         <span>{val.term}</span>
     ))}
   </div>
 )
}

答案 1 :(得分:1)

问题出在这里:let {words, word} = this.state; this.state还没有单词属性。您可以像这样初始化this.state

this.state = {
   words: [],
   word: {}
};

可以自由提问

答案 2 :(得分:0)

问题中的代码有两个问题:

  1. wordsword未定义。
  2. words中的render()函数中通过keys进行的迭代未正确设置。

感谢这个问题的答案和评论,这是我最终使用的代码:

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

class App extends Component {
  constructor () {
    super()
    this.state = {
      words : [],
      word : {}
    }
    this.getWords = this.getWords.bind(this)
    this.getWord = this.getWord.bind(this)
  }

  componentDidMount () {
    this.getWords()
  }

  fetch (endpoint) {
    return window.fetch(endpoint)
      .then(response => response.json())
      .catch(error => console.log(error))
  }

  getWords () {
    this.fetch('/api/words')
      .then(words => {
        if (words.length) {
          this.setState({words: words})
          this.getWord(words[0].id)
        } else {
          this.setState({words: []})
        }
      })
  }

  getWord (id) {
    this.fetch(`/api/words/${id}`)
      .then(word => this.setState({word: word}))
  }

  render () {
    let {words} = this.state
    return (
      <ul className="words-container">
        {Object.keys(words).map((key) => {
          return (
            <li className="word-container" key={key}>
              {words[key].term}: {words[key].definition}.
            </li>
          )
        })}
      </ul>
    )
  }
}

export default App;