从孩子到父母应对沟通问题

时间:2018-12-22 18:45:55

标签: javascript reactjs ecmascript-6 components

我正在构建一个猜谜游戏,其中的问题和选择逻辑位于名为Questions的组件中。我无法让App阅读问题代码。我希望App中的状态根据子组件中的选择进行更新。

我一直在尝试对How to pass data from child component to its parent in ReactJS?https://malithjayaweera.com/2018/01/reactjs-passing-data-react-components/的解决方案进行反向工程,但是我不清楚如何将其应用于我的项目。

应用程序:

import React, { Component } from 'react';
import './App.css';
import Timer from "./Timer";
import Questions from "./Questions/Questions.js";
import Results from "../src/Results";

class App extends Component {

  state = {
    totalTrue: 0,
    totalFalse: 0,
  }

  componentDidMount() {
    console.log(`TotalTrue: ${this.state.totalTrue}`);
    console.log(`TotalFalse: ${this.state.totalFalse}`);
  }

  // submit button
  handleFormSubmit = event => {
    event.preventDefault();
    console.log("submit button clicked");
  };

  callbackHandlerFunction = (selectedOption) => {
    this.setState({ selectedOption });
  }

  render() {
    return (

      <div className="parallax">

      <div className="App">

      <div className="wrapper">

      <div className="headerDiv">
      <h1>Pixar Trivia!</h1>
    </div>

    <div className="timerDiv">
      <Timer />
      </div>

      <div className="questionSection">
      <Questions
    handleClickInParent={this.callbackHandlerFunction}
    />
    </div>

    <div>
    <button onClick={this.handleFormSubmit}>Submit</button>
      </div>

    {/* this.state.articles.length > 0 && ...*/}
  <div className="resultsDiv">
      <Results
    totalTrue={this.state.totalTrue}
    totalFalse={this.state.totalFalse}
    />
    </div>

    </div>

    </div>

    </div>
  );
  }
}

export default App;

问题:

import React, { Component } from "react";
import Select from "react-select";
import "./Questions.css";

const answerChoices = [
    {
        id: 1,
        text: "1. The background image is the carpet from Sid's house in Toy Story. What movie inspired it?",
        answers: [
        {
            label: "2001: A Space Odyssey",
            value: false
        },
        {
            label: "The Shining",
            value: true
        },
        {
            label: "One Flew Over the Cuckoo's Nest",
            value: false
        },
        {
            label: "The Godfather",
            value: false
        }
        ]
},
  ---- full questions cut for space. I'm using https://github.com/JedWatson/react-select and the functionality works. ----
{
    id: 8,
    text: "8. Who was the original voice of Marlin from “Finding Nemo”?",
    answers: [
        {
            label: "Albert Brooks",
            value: false
        },
        { 
            label: "Denis Leary",
            value: false
        },
        {
            label: "Brad Garrett",
            value: false
        },
        {
            label: "William H. Macy",
            value: true
        }
        ]
    }
];

class Questions extends Component {

state = {
    answerChoices,
    selectedOption: null,
}

handleChange = (selectedOption) => {
    this.setState({ selectedOption });
    console.log(`Option selected:`, selectedOption);

    const answerValue = selectedOption.value;
    if (answerValue === true) {
        // console.log(answerValue);
        this.setState({totalTrue: this.totalTrue + 1}, () => {
            console.log(`New TotalTrue: ${this.totalTrue}`);
        });
    };
    if (answerValue === false) {
        // console.log(answerValue);
        this.setState({totalFalse: this.totalFalse + 1}, () => {
            console.log(`New TotalFalse: ${this.totalFalse}`);
        });
    };
    this.props.handleClickInParent({selectedOption});

  }

render() {
    // const { selectedOption } = this.state;

    return (

        <div className="questionsDiv">

            <ol>
                {this.state.answerChoices.map(question => {
                return (

                    <div className="individualQuestions" key={question.id}>

                        {question.text}

                        <Select
                            value={this.selectedOption}
                            onChange={this.handleChange}
                            options={question.answers}
                        />

                    </div>

                    )  
                })}
            </ol>

        </div>

    )
  }

}

export default Questions;

2 个答案:

答案 0 :(得分:0)

查看Question中的这一行:

this.props.handleClickInParent({selectedOption});

它将{ selectedOption }中的callbackHandlerFunction传递到App。现在,App中的最后一个函数采用单个参数selectedOption,并继续使用它来更新状态。总之,您正在使用以下命令更新App中的状态:

this.setState({ { selectedOption } }); // this is wrong.

要解决此问题,请在this.props.handleClickInParent(selectedOption)中使用Question(无花括号)。

或者,如果您忽略上述内容,也可以通过更改callbackHandlerFunction的签名来解决此问题,使其看起来像这样:

callbackHandlerFunction = ({ selectedOption }) => { // note the curly braces.
    this.setState({ selectedOption });
}    

答案 1 :(得分:0)

我做了一些更改,现在可以正常工作了。

代码现在看起来像这样。

callbackHandlerFunction = ( selectedOption ) => {
  const answerValue = selectedOption.value;
  if (answerValue === true) {
      // console.log(answerValue);
      this.setState({totalTrue: this.state.totalTrue + 1}, () => {
          console.log(`New TotalTrue: ${this.state.totalTrue}`);
      });
  };
  if (answerValue === false) {
      // console.log(answerValue);
      this.setState({totalFalse: this.state.totalFalse + 1}, () => {
          console.log(`New TotalFalse: ${this.state.totalFalse}`);
      });
  };
}  

handleChange = (selectedOption) => {

    this.props.handleClickInParent(selectedOption);
  }