【问题标题】:How to pass values between components in React JS?如何在 React JS 中的组件之间传递值?
【发布时间】:2019-03-21 16:03:55
【问题描述】:

所以我在这个任务上已经坚持了大约一个星期。我在这里问了一个关于它的问题,但由于我对 React 缺乏经验,我仍然无法弄清楚如何解决它。作业如下:

这个项目的目标是创建一个模拟 一家咖啡馆的经营。您将需要为 顾客、咖啡师和咖啡机。

客户组件

这是“面向用户”的组件。在这里你应该有3个选项 将导致此组件触发自定义事件的项目。这些 选项包括:Drip brew、法式压榨和浓缩咖啡。

当点击其中一个对象时,它应该突出显示并保持 突出显示,直到单击另一个。

咖啡师组件

该组件接受订单,并在 DOM 上显示响应, 格式如下:

“一个 {{ order_type }}?那将是 {{ order_value }}。”

接受新订单时,播放动画以过渡到下一个订单 文本,并在新文本中过渡。

延迟 5 秒后(使用 setTimeout 方法),触发 事件开始准备咖啡。更改此文本 要读取的组件,“等待 {{ order_type}}”

这个组件还需要一个方法,当 机器完成它的准备工作。这种“coffeeFinished”方法应该 显示如下消息:“这是你{{ order_type }},享受吧!”。

接受新订单时,播放动画以过渡到下一个订单 文本,并在新文本中过渡。

机器组件

这个组件,当它的“brewCoffee”方法被调用时,应该显示 向用户显示一条消息,显示“当前正在酝酿:{{ order_type }}"。

再一次,使用 setTimeout,让这个组件在之前等待 5 秒 触发“brewingComplete”事件。当这个事件被触发时,也 将此组件的输出更改为“{{ order_type }} 已完成。”

在冲泡咖啡时,需要为加载栏设置动画 显示距离该过程结束还有多长时间。

应用程序对象

应用程序对象将负责监听每个 从您的组件触发的事件,并调用适当的 下一行的方法。例如,当机器组件 触发事件“brewingComplete”,应用程序应响应 通过调用 Barista 上的交付订单方法的事件 组件。

此外,该组件应将当前订单名称存储在 它的属性。这是应该引用的变量 显示咖啡师正在冲泡和重复的订单。

我遇到的问题是使用一个组件,在这种情况下,当用户按下按钮时,并在其他组件中使用这些值和超时功能。到目前为止我所拥有的是:

App.js

import React, { Component } from 'react';
import './App.css';
import './Customer.js';
import Customer from './Customer.js';
import './Barista.js';
import Barista from './Barista.js';
import './CoffeeMachine.js';
import CoffeeMachine from './CoffeeMachine.js';

class App extends Component {

  //The State with all the stuff that gets updated along the way
  state = {
    coffee: "",
      value: 0,
      bgColor: 'transparent'
  }


  //I apparently can't comment in the render thing without it appearing on the page. So, the Green box for the Customer Component, the Orange box for the Barista Component, and the Blue Box for the Machine component.
  render() {

    return (
      <div className="App">

          <div className="row" id="green">

          <Customer order = {(coffeeSelect, value) => {this.send(coffeeSelect, value)}}/>
          </div>


          <div className="row" id="orange">
          <Barista coffeeSelect = { this.state.coffee } value = { this.state.value }/>
          </div>


          <div className="row" id="blue">
          <CoffeeMachine coffeeSelect = { this.state.coffee } value = { this.state.value }/>
          </div>
      </div>
    )
  }

  //Sends the selected values to the other components
  send(coffeeSelect, value) {
    this.setState({coffee: coffeeSelect, value: value});
  }



}

export default App;

Customer.js

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

class Customer extends Component {


//Each button has a div to be highlighted upon being selected
    render() {

        return(
            <div>

            <div className="button">
            <button onClick={() => { this.optionSelect("Drip")}}>
        Drip
        </button>
        </div>

        <div className="button">
        <button onClick={() => { this.optionSelect("French Press")}}>
        French Press
        </button>
        </div>

            <div className="button">
        <button onClick={() => { this.optionSelect("Espresso")}}>
        Espresso
        </button>


            </div>

        </div>);
    }


    //Receives the brew, and assigns it to its matching cost
    optionSelect(userChoice) {
        var coffeeSelect = userChoice;
        var value = 0;

        if (coffeeSelect === "Drip"){
            value = 5;
        } else if (coffeeSelect === "French Press"){
            value = 6;
        } else if (coffeeSelect === "Espresso"){
            value = 3;
        }

        this.props.order(coffeeSelect, value);
        console.log(coffeeSelect);
        console.log(value);



    }



}

export default Customer;

Barista.js

import React, { Component } from 'react';

class Barista extends Component {

    //The default text in the Barista Component until the user sends it the coffee and cost
    state = {
        text: "Hello, How May I Help You Today?",
        orderText: "One " + this.props.coffee + "? That will be $" + this.props.value
    }

    //This is where I've hit the brick wall. I just need to get the buttons to also call this thing but everything I've looked up just gives me errors. If I could figure out where to call this I can do the timer to "prep" the coffee.
    confirm(){
        this.setState({ text: "One " + this.props.coffee + "? That will be $" + this.props.value});
        setTimeout(() => {this.waiting()}, 5000);
    }

    waiting() {
        this.setState({ text:"Waiting for " + this.props.coffee});
        setTimeout(() => {this.finish()}, 5000);
    }

    finish() {
        this.setState({ text: "Here is your " + this.props.coffee + ". Enjoy!"});
    }


    render() {

        return(

            <div>

            {this.state.text}



                </div>
        )

    }


}

export default Barista;

到目前为止,我完全被卡住了,我还没有任何机器组件。虽然我毫不怀疑我在这里有很多问题,但我的主要问题是当用户按下客户组件中的按钮时,如何更改咖啡师组件中的文本。是否有一些简单的东西我遗漏了或者我完全不合时宜?

【问题讨论】:

  • 你有完整代码的仓库吗?
  • 由于这是一个作业,我不想给出答案,但是,您要使用的是HOC 或高阶组件。 HOC 就像咖啡店本身一样。它包含所有children 组件,并且还可以共享内容(您实际上拥有此设置的基础App)。但是,您需要提升需要在孩子之间使用和共享的state 和/或methods。你很近。你有它的基础,你只需要更多地利用它。此外,在render 方法中,您可以像这样插入 cmets:{ /* I'm a comment! */ }
  • 你应该使用一些像 redux 这样的状态管理,因为它认为这就是他们想要的,尽管你可以使用我们的 redux 来做到这一点。

标签: reactjs components


【解决方案1】:

编辑:修复了必须按两次按钮的问题。

    import React, { Component } from 'react';

    class Barista extends Component {

    //The default text in the Barista Component until the user sends it the coffee and cost
    state = {
        text: "Hello, How May I Help You Today?"

    }

    //The domino effect of messages. Upon being sent the brew and value variables, the confirm function is called which calls the waiting function which calls the finish function.
    confirm(){
        this.setState({ text: "One " + this.props.coffee + "? That will be $" + this.props.value});
        setTimeout(() => {this.waiting()}, 5000);
    }

    waiting() {
        this.setState({ text:"Waiting for " + this.props.coffee});
        setTimeout(() => {this.finish()}, 1000);
    }

    finish() {
        this.setState({ text: "Here is your " + this.props.coffee + ". Enjoy!"});
    }

    componentWillUpdate(nextProps,nextState) {
        if (this.props.coffee !== null && this.state === nextState) {
            setTimeout(() => {this.confirm()}, 3000);
        }
    }

    render() {

console.log(this.props.coffee);

        return(

            <div>

            {this.state.text}

    </div>
    )
    }
}

export default Barista;

【讨论】:

  • 这是一个非常糟糕的解决方案,也是反应中的主要反模式。您正在尝试使用像 componentWillUpdate 之类的黑客来更新应该存储在父级中的子级状态
  • 什么是反模式?你是说我应该在应用程序中使用一个函数来调用咖啡师中的东西吗?
【解决方案2】:

你正在成为所有 React 问题中最经典的受害者。您只是根据初始状态渲染视图,而不是响应状态变化。

这个超级简单的更改将解决您的问题:

// Barista.js

....

render() {
  return (
    <div>
      {"One " + this.props.coffee + "? That will be $" + this.props.value}
    </div>
  )
}
....

现在,当您的父状态因单击 Customer 中的按钮而发生变化时,Barista 渲染方法将显示更新的消息,因为 this.props.value 已更改。

注意:你的道具命名不正确..在App你叫它coffeeSelect

<Barista coffeeSelect=

.. 但在 Barista 中,您将其称为 this.props.coffee,因此请确保将您的道具命名为相同。在App 中应该是:

<Barista coffee=

【讨论】:

  • 这是我最初尝试添加计时器部分之前的内容。 (虽然我确实错过了道具命名,但谢谢。)这个问题是渲染上的文本是“一个?那将是 0 美元。”它需要是空白的或有类似“我今天能帮你什么?”之类的内容。然后在用户按下按钮后更改为“That will be $”。
  • 所以使用条件渲染reactjs.org/docs/conditional-rendering.html你读过文档吗?
  • 我可能没有正确理解该文档。当我应用条件时,单击客户组件中的按钮后收到错误“超出最大更新深度”。据我了解,这是因为渲染只是由于条件而一遍又一遍地重复。我正在尝试这样做,如果咖啡的值只是空字符串,那么它将显示欢迎消息,并且在具有值后它将更改为订单和价格字符串。
  • 你能用你添加的“条件渲染”代码更新你的问题吗?条件不会超过最大更新深度。它发生是因为您在渲染周期中某处调用 setState
  • 已更新。他们在文档中使用的示例是添加一个按钮,因此我尝试对其进行调整,而不是更改按钮来更改 div 中的文本。
猜你喜欢
  • 2020-04-30
  • 2019-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-25
  • 2018-07-08
相关资源
最近更新 更多