【问题标题】:Pass database data from express.js server to react.js component将数据库数据从 express.js 服务器传递到 react.js 组件
【发布时间】:2019-01-16 03:54:14
【问题描述】:

这是一个带有 express.js 后端的 react 应用。我有一个连接到我的 server.js 文件的 mysql 数据库,它似乎连接正常。我的问题是我想将该数据传递给我的反应应用程序并在那里显示。

我的 server.js 数据库连接

app.get('api/listitems', (req, res) => {     

connection.connect();    
connection.query('SELECT * from list_items', (error, results, fields) => {    
    if (error) throw error;    
    res.send(results)    
});  
connection.end(); 

});

所以这应该从数据库中获取“list_items”记录

下面是我的 react.js 代码。我想在杂货清单 h3 下显示记录。

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

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: ['first item']
    };

  }

  render() {
    return (
      <div className="App">
        <h3>Grocery List</h3>
        {this.state.data}
      </div>
    );
  }
}

export default App;

我知道这是一个简单的概念,但我是后端开发的新手。我找到的教程让我了解了这一点,但是我在找到一个简单地解释如何从后端传递和显示数据到前端的教程时遇到了问题。

【问题讨论】:

    标签: mysql node.js reactjs express


    【解决方案1】:
    **index.js**
    
    import React from 'react';
    import { render } from 'react-dom';
    import App from './components/app';
    import { BrowserRouter } from 'react-router-dom'
    import { Provider } from 'react-redux';
    import store, { history } from './store';
    
    const route = (
      <Provider store={store}>
      <BrowserRouter>
            <App />
      </BrowserRouter>
      </Provider>
    )
    render(route,document.getElementById('app'))
    
    **action/listItemAction.js**
    
    export const ListItemSuccess = (data) => {
        return {type: 'GET_LIST_ITEMS'};
    }
    
    export const getListItems = () => {
        return (dispatch) => {
            return axios.get('http://localhost:5000/api/listitems')
            .then(res => {
               dispatch(ListItemSuccess(res));
            })
            .catch(error=>{
                throw(error);
            })      
        };
    }
    
    **reducers/listItems.js**
    
    const listItems = (state = [], action) => {
      switch(action.type){
        case 'GET_LIST_ITEMS':
          return action.res.data;
        default:
          return state;
      }
    }
    
    export default listItems;
    
    **store.js**
    
    import { createStore, applyMiddleware, compose } from 'redux';
    import thunk from 'redux-thunk'
    import listItems from './reducers/listItems.js';
    
    const store = createStore(listItems,  compose(
        applyMiddleware(thunk),
        window.devToolsExtension ? window.devToolsExtension() : f => f
      ));
    
    export default store;
    
    **App.js**
    
    import React, { Component } from 'react';
    import { bindActionCreators } from 'redux';
    import { connect } from 'react-redux';
    import './App.scss';
    import getListItems from './action/listItemAction.js
    
    class App extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          data: [],
          isLoading: true,
        };
    
      }
      componentWillMount() {
        this.props.getListItems().then(() => {
          this.setState({data: this.props.listItems, isLoading:false});
        }).catch(error => {
            throw(error);
        });
      }
      render() {
        return (
          <div className="App">
            <h3>Grocery List</h3>
            {this.state.isLoading ? <p>Loading...</p>
              : this.state.error ? <p>Error during fetch!</p>
              : (
                  <ul>
                    this.state.data.map(item => <li>{item}</li>)
                  </ul>
                )}
          </div>
        );
      }
    }
    
    const mapStateToProps = (state) => {
        return {
          listItems: state.listItems
        };
    };
    const mapDispatchToProps = (dispatch) => {
        return {
            getListItems: bindActionCreators(getListItems, dispatch),
        };
    };
    
    export default connect(mapStateToProps,mapDispatchToProps)(App);
    

    【讨论】:

    • 感谢您的评论,但我正在寻找更香草的东西。我对这些东西很陌生,并且正在努力工作。我对 redux 或 axios 还不太了解。我相信这些会让事情变得更容易,但为了时间,我只想要一个基本的 javascript,反应解决方案。谢谢!
    【解决方案2】:

    您想向后端发出 GET 请求以异步获取数据。如果您想在您的 App 组件首次挂载时获取数据,您可以使用 fetch in componentDidMount 来调用您的后端端点。这是一个示例,带有 loading 回退和基本错误处理:

    class App extends Component {
      state = {
        data: [],
        loading: true,
        error: false
      }
      ...
      componentDidMount() {
        // Pick whatever host/port your server is listening on
        fetch('localhost:PORT/api/listitems')
          .then(res => { // <-- The `results` response object from your backend
            // fetch handles errors a little unusually
            if (!res.ok) {
              throw res;
            }
            // Convert serialized response into json
            return res.json()
          }).then(data => {
            // setState triggers re-render
            this.setState({loading: false, data});
          }).catch(err => {
            // Handle any errors
            console.error(err);
            this.setState({loading: false, error: true});
          });
      }
    
      render() {
        return (
          <div className="App">
            <h3>Grocery List</h3>
            // The app will render once before it has data from the
            // backend so you should display a fallback until
            // you have data in state, and handle any errors from fetch
            {this.state.loading ? <p>Loading...</p>
              : this.state.error ? <p>Error during fetch!</p>
              : (
                  <ul>
                    this.state.data.map(item => <li>{item}</li>)
                  </ul>
                )}
          </div>
        );
      }
    }
    

    fetch 不会拒绝 HTTP 错误状态 (404, 500),这就是为什么第一个 .then 有点奇怪。 .catch 将在此处记录响应和状态,但如果您想查看来自服务器的错误消息,您需要执行以下操作:

    if (!res.ok) {
      return res.text().then(errText => { throw errText });
    }
    

    请参阅 https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch 了解更多信息,或探索其他数据获取库,例如 axios

    【讨论】:

    • 出于某种原因,它不断向我抛出此错误。 “未处理的拒绝(TypeError):err.text 不是函数”,当我评论该行时,它只返回“获取期间错误!”杂货清单下的字符串...必须缺少其他东西。我检查了所有的数据库连接以确保它们被找到并且其他所有东西都检查出来了。
    • 会不会是端口问题? express.js 服务器在端口 5000 上运行,react-app 在 3000 上运行。我正在使用 mamp 的 mysql 数据库。 Mamp 说 mysql 在端口 3306 上运行。不确定这是否重要。当我第一次启动 Express 时,它会在终端上打印出我想要的记录。所以我知道 express 正在提取适当的数据。
    • 我已经更新了我的示例,.catch 期待响应中出现错误,但它没有处理连接错误,这听起来像是您可能遇到的。这种方式应该更健壮一些。
    • Re: 端口,听起来 5000 是对的,它将是您的快速服务器正在侦听对 api/listitems 的请求的端口(而不是 DB 端口)。您的快速代码中可能有app.listen(SOME_PORT, callback),应该是那个。此外,端点通常以斜杠开头:/api/listitems - 这可能是问题的一部分。上面编辑过的代码应该会给你更好的错误日志来调试它。
    • 我发现了问题所在。它最终成为 CORS 发行的。我需要将底部代码放在我的 server.js 中。 app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); });
    猜你喜欢
    • 2017-05-06
    • 2018-06-30
    • 2017-10-17
    • 2017-10-03
    • 2019-05-26
    • 2018-07-08
    • 2017-07-21
    • 2018-01-19
    • 1970-01-01
    相关资源
    最近更新 更多