React.js使用共享的onClick函数定位单个元素

时间:2018-04-15 21:53:28

标签: javascript reactjs

我是编码和React.js的新手,所以非常感谢任何帮助我学习错误的行为!我正在一个带有谜语的页面上创建多张卡片,其中答案通过css隐藏。我正在使用onClick函数(“toggleAnswer”)来切换每个答案的状态以更改className,以便答案可见或隐藏。目前,onClick事件正在改变所有答案的状态。我意识到这是因为我的代码没有针对特定元素,但我不确定如何做到这一点。怎么能实现这一目标?我的代码目前是这样的:

// RiddlesPage where toggleAnswer function is defined
class RiddlesPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            questionData: [],
            isHidden: true
        };
        this.getPageData = this.getPageData.bind(this);
        this.toggleAnswer = this.toggleAnswer.bind(this);
    }
    getPageData() {
        console.log("we hit getPageData function starting --");
        helpers.getRiddlesPage().then(data => {
            console.log("this is the result", data);
            this.setState({
                questionData: data[0].questionData,
            });
        });
    }
    toggleAnswer(e) {
        this.setState({ isHidden: !this.state.isHidden });
    }
    componentWillMount() {
        this.getPageData();
    }
    render() {
        const answerClass = this.state.isHidden ? "answer-hide" : "answer";
        return (
            <div>
                <Riddles>
                    {this.state.questionData.map((data, index) => {
                        return (
                            <RiddlesItem
                                key={index}
                                id={index}
                                question={data.question}
                                answer={data.answer}
                                button={data.buttonURL}
                                answerClass={answerClass}
                                onClick={this.toggleAnswer}
                            />
                        );
                    })}
                </Riddles>
            </div>
        );
    }
}
export default RiddlesPage;

// Riddles Component
import React from "react";
import "./riddles.css";
const Riddles = props => (
    <div id="riddles-row">
        <div className="container">
            <div className="row">
                <div className="col-12">
                    <div>{props.children}</div>
                </div>
            </div>
        </div>
    </div>
);
export default Riddles;

// RiddlesItem Component where onClick function is set as a prop
import React from "react";
import "./riddles.css";
const RiddlesItem = props => (
  <div>
      <div className="card-body">
            <p id="question">{props.question}</p>    
            <img
              className="img-fluid"
              id={props.id}
              src={props.button}
              onClick={props.onClick}
              alt="answer button"
            />     
        <p className={props.answerClass}> {props.answer} </p>
      </div>
  </div>
);
export default RiddlesItem;

1 个答案:

答案 0 :(得分:0)

您必须跟踪状态中显示的每个答案(在数组或其他内容中)。

<强>第一

在onclick函数中发送答案的索引。在该函数中,检查它是否存在于“shownAnswers”数组中,并添加或删除它。

onClick={e => props.onClick(e, props.id)}

toggleAnswer(e, index) {
    if (this.state.shownAnswers.indexOf(index) > -1) {
        this.setState({
            shownAnswers: this.state.shownAnswers.filter(val => val !== index)
        });
    } else {
        this.setState({
            shownAnswers: this.state.shownAnswers.concat(index)
        });
    }
}

,然后

当你将类名传递给子组件时,检查它的索引是否在“shownAnswers”数组中,以决定传递哪个类名。

answerClass={this.state.shownAnswers.indexOf(index) > -1 ? "answer" : "answer-hide"}

建立你的例子,它可能看起来像这样(未经测试):

// RiddlesPage where toggleAnswer function is defined
class RiddlesPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            questionData: [],
            shownAnswers: []
        };
        this.getPageData = this.getPageData.bind(this);
        this.toggleAnswer = this.toggleAnswer.bind(this);
    }
    getPageData() {
        console.log("we hit getPageData function starting --");
        helpers.getRiddlesPage().then(data => {
            console.log("this is the result", data);
            this.setState({
                questionData: data[0].questionData,
            });
        });
    }
    toggleAnswer(e, index) {
        if (this.state.shownAnswers.indexOf(index) > -1) {
            this.setState({ shownAnswers: this.state.shownAnswers.filter(val => val !== index) });
        } else {
            this.setState({ shownAnswers: this.state.shownAnswers.concat(index) });
        }
    }
    componentWillMount() {
        this.getPageData();
    }
    render() {
        return (
            <div>
                <Riddles>
                    {this.state.questionData.map((data, index) => {
                        return (
                            <RiddlesItem
                                key={index}
                                id={index}
                                question={data.question}
                                answer={data.answer}
                                button={data.buttonURL}
                                answerClass={this.state.shownAnswers.indexOf(index) > -1 ? "answer" : "answer-hide"}
                                onClick={this.toggleAnswer}
                            />
                        );
                    })}
                </Riddles>
            </div>
        );
    }
}
export default RiddlesPage;

// Riddles Component
import React from "react";
import "./riddles.css";
const Riddles = props => (
    <div id="riddles-row">
        <div className="container">
            <div className="row">
                <div className="col-12">
                    <div>{props.children}</div>
                </div>
            </div>
        </div>
    </div>
);
export default Riddles;

// RiddlesItem Component where onClick function is set as a prop
import React from "react";
import "./riddles.css";
const RiddlesItem = props => (
  <div>
      <div className="card-body">
            <p id="question">{props.question}</p>    
            <img
              className="img-fluid"
              id={props.id}
              src={props.button}
              onClick={e => props.onClick(e, props.id)}
              alt="answer button"
            />     
        <p className={props.answerClass}> {props.answer} </p>
      </div>
  </div>
);
export default RiddlesItem;