简体   繁体   English

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

[英]How can I render a React component from server.js to App.js using post?

I'm a beginner in React and Javascript so still learning :) 我是React和Javascript的初学者,所以仍然在学习:)

I'm creating a magic 8 ball application where once the Button is clicked, using the post method, I want to return a random answer (one of the 20 in my server.js) back to the same App.js file... I assume as a response? 我正在创建一个神奇的8球应用程序,在其中使用post方法单击按钮后,我想将随机答案(server.js中的20个之一)返回到相同的App.js文件...我认为是回应?

How can I render an HTML element (ie answers[number] ) back to my App.js where my Answer paragraph is? 如何将HTML元素(即Answers answers[number] )呈现回我的Answer段落所在的App.js中?

Sidenote: I've tried using res.send() to set it up - is this along the right lines? 旁注:我尝试使用res.send()进行设置-这是否正确?

I am using node.js and express as the server. 我正在使用node.js并表示为服务器。

EDIT: full server.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)
})

EDIT: full App.js: 编辑:完整的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;

This sort of stuff is well explained in the docs . 这些内容在docs中已得到很好的解释。

Everytime you do an API request you need to use state because it is a side-effect. 每次您执行API请求时,都需要使用状态,因为它是一个副作用。 I suggest you read the docs and understand it, but to make it work in your component add this at the beginning of your component: 我建议您阅读并理解文档,但要使其在组件中起作用,请在组件的开头添加以下内容:

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

    /* Rest of component code */
}

And change your fetch request to look like this: 并更改您的提取请求,如下所示:

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

By adding state, you're also going to have problems with binding so change your method declaration to an arrow function, from this: 通过添加状态,绑定也将出现问题,因此将方法声明更改为箭头函数,如下所示:

handleSubmit(event) { /* code */ }

to this: 对此:

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

To display the result in your answer paragraph do this: 要在您的答案段落中显示结果,请执行以下操作:

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

Basically, you need to save the result of the fetch call to your component state. 基本上,您需要将fetch调用的结果保存到组件状态。 Using setState, it will automatically trigger a rerender of your component and display the new answer. 使用setState,它将自动触发组件的重新呈现并显示新答案。

Try this: 尝试这个:

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

then inside render(): 然后在render()中:

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

EDIT: 编辑:

You may need to parse the response as json eg 您可能需要将响应解析为json例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM