我如何使用post将React组件从server.js渲染到App.js?

时间:2019-03-13 21:41:12

标签: javascript node.js reactjs express

我是React和Javascript的初学者,因此仍在学习:)

我正在创建一个神奇的8球应用程序,在其中单击按钮后,使用post方法,我想将随机答案(在server.js中为20个之一)返回到相同的App.js文件...我认为是回应?

如何将HTML元素(即answers[number])呈现回我的答案段落所在的App.js中?

旁注:我尝试使用res.send()进行设置-这是否正确?

我正在使用node.js并表示为服务器。

编辑:完整的server.js:

const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()

app.prepare()
.then(() => {
  const server = express()

  server.get('/p/:id', (req, res) => {
    const actualPage = '/post'
    const queryParams = { title: req.params.id }
    app.render(req, res, actualPage, queryParams)
  })

  server.get('*', (req,res) => {
    return handle(req,res)
  })

  server.listen(3000, (err) => {
    if (err) throw err
    console.log('> Ready on http://localhost:3000')
  })

  /* Return random answer after question is submitted.*/
  server.post('/', (req,res) => {
    const answers = [
      "It is certain.",
      "It is decidedly so.",
      "Without a doubt.",
      "Yes - definitely.",
      "You may rely on it.",
      "As I see it, yes.",
      "Most likely.",
      "Outlook good.",
      "Yes.",
      "Signs point to yes.",
      "Reply hazy, try again.",
      "Ask again later.",
      "Better not tell you now.",
      "Cannot predict now.",
      "Concentrate and ask again.",
      "Don't count on it.",
      "My reply is no.",
      "My sources say no.",
      "Outlook not so good.",
      "Very doubtful.",
      "Computer says no."
    ]
    const number = Math.floor(Math.random()*21);
    console.log("Raw answer: ");
    console.log(answers[number]);
    res.status(200).send(answers[number]);
    console.log("Response: ");
    console.log(res);
  })

})
.catch((ex) => {
  console.error(ex.stack)
  process.exit(1)
})

编辑:完整的App.js:

import Layout from '../components/MyLayout.js'
import Header from '../components/Header.js'
import Link from 'next/link'
import { Component } from "react";
import { spring } from 'popmotion';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      count: 0,
      response: undefined
    };
    this.incrementCounter = this.incrementCounter.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  componentDidMount() {
    this.setState({
      count: parseInt(localStorage.getItem("count")) || 0
    });
  }

  incrementCounter() {
    const count = this.state.count + 1;
    localStorage.setItem("count", count);
    this.setState({
      count: count
    });
  }

  handleSubmit = (event) => {
    event.preventDefault();
    fetch('/', { method: 'POST' }).then(response => this.setState({response}));
    console.log("this.state.response:");
    console.log(this.state.response);
  }

  render() {
    return (
        <main>
          <Header />
            <div style={{display: 'flex',  justifyContent:'center', alignItems:'center'}}>
              <h1 style={{ fontFamily:"Arial", fontSize:"50px" }}>Magic 8 Ball</h1>
            </div>

            <div style={{display: 'flex',  justifyContent:'center', alignItems:'center'}}>
              <form className="question-input" onSubmit={this.handleSubmit}>
                <TextField
                  id="inputquestion"
                  autoComplete="off"
                  placeholder="Ask your question..."
                  margin="normal"
                />
                <Button
                  variant="contained"
                  type="submit"
                  color="primary"
                  onClick={this.incrementCounter.bind(this)}
                  id="submitquestion"
                  style={{ width: "100px", fontSize:17 }}>Shake Me!
                </Button>
              </form>
            </div>

            <div style={{display: 'flex',  justifyContent:'center', alignItems:'center'}}>
              <p>Answer: </p>
              <p>Question count: {this.state.count}</p>
            </div>
        </main>
    )
  }
}

export default App;

2 个答案:

答案 0 :(得分:0)

docs中对此类内容进行了很好的解释。

每次执行API请求时,都需要使用状态,因为它是一个副作用。我建议您阅读并理解文档,但要使其在您的组件中起作用,请在组件的开头添加以下内容:

class BlaBla extends Component {
    state = {
        response: undefined
    };

    /* Rest of component code */
}

并更改您的提取请求,如下所示:

fetch('/', { method: 'POST' }).then(response => this.setState({response}));

通过添加状态,绑定也会遇到问题,因此将方法声明从以下位置更改为箭头函数:

handleSubmit(event) { /* code */ }

对此:

handleSubmit = (event) => { /* code */ }

要在答案段落中显示结果,请执行以下操作:

<p> Answer: {this.state.response} </p>

答案 1 :(得分:0)

基本上,您需要将fetch调用的结果保存到组件状态。使用setState,它将自动触发组件的重新渲染并显示新答案。

尝试一下:

handleSubmit(event) {
    event.preventDefault();
    // assuming the fetch works ok...
    fetch('/', { method: 'POST' }).then(response => 
      response.json().then(data => this.setState({answer:response}) )
     )
  }

然后在render()中:

<div style={{display: 'flex',  justifyContent:'center', alignItems:'center'}}>
  <p>Answer:{this.state.answer}</p>
  <p>Question count: {this.state.count}</p>
</div>

编辑:

您可能需要将响应解析为json,例如

fetch('/', { method: 'POST' }).then(response => 
  this.setState({answer:JSON.parse(response)})
)