从子组件中反应访问父节点的dom节点

时间:2017-08-24 11:09:39

标签: javascript reactjs ecmascript-6

我有一个网格组件如下:

import React, { Component } from 'react';

import Action from './action.jsx';

class Grid extends Component {

    constructor(props) {
        super(props);
        this.maxN = 110;
        this.tempArray = [];
        this.question;
    }

    getRandomN() {
        var randomN = Math.floor((Math.random() * this.maxN) + 1);

        if(this.tempArray.indexOf(randomN) === -1) {
            this.tempArray.push(randomN);
        }
        else {
            randomN = this.getRandomN();
        }

        return randomN;
    }

    getRandomQuestion() {   
        this.question = this.props.current.data.questions[this.getRandomN()];
        return this.question;
    }

    render() {
        this.getRandomQuestion();

        return (
            <section className="game">
                <div className="grid">

                    <div className="row">
                        <div ref="n1"></div>
                        <div ref="n2"></div>
                        <div ref="n3"></div>
                        <div ref="n4"></div>
                        <div ref="n5"></div>
                        <div ref="n6"></div>
                    </div>

                    <div className="row">
                        <div ref="n7"></div>
                        <div ref="n8"></div>
                        <div ref="n9"></div>
                        <div ref="n10"></div>
                        <div ref="n11"></div>
                        <div ref="n12"></div>
                    </div>

                    <div className="row">
                        <div ref="n13"></div>
                        <div ref="n14"></div>
                        <div ref="n15"></div>
                        <div ref="n16"></div>
                        <div ref="n17"></div>
                        <div ref="n18"></div>
                    </div>

                    <div className="row">
                        <div ref="n19"></div>
                        <div ref="n20"></div>
                        <div ref="n21"></div>
                        <div ref="n22"></div>
                        <div ref="n23"></div>
                        <div ref="n24"></div>
                    </div> 
                </div>

                <Action question={this.question} getRandomQuestion={this.getRandomQuestion.bind(this)}/>
            </section>
        );
    }
}

export default Grid;

内部&#34;行动&#34;组件,基于来自&#34; getNewQuestion&#34;的正确或错误答案我需要从网格组件中访问随机网格元素。 (任何随机从&#34; n1&#34;到&#34; n24&#34;分配给每个ref属性)

import React, { Component } from 'react';

class Action extends Component {
    constructor(props) {
        super(props);

        this.state = {
            question: props.question
        }
    }

    getNewQuestion(e) {
        console.log(this.state.question.correct_option);

        let answerId = "option_" + this.state.question.correct_option;

        if(e.target.getAttribute('data-question') == answerId) {
            this.setState({
                question: this.props.getRandomQuestion()
            });
        }
        else {
            console.log('wrong');

            React.findDOMNode(this.refs.n1).classList.add('fdsdfsdfsdfsdfsfsdf');
        }
    }

    render() {
        let state = this.state;

        return(
            <div className="action">
                <div className="action-question">
                    <h3>{state.question.question}</h3>
                </div>

                <div className="action-answers">
                    <p data-question="option_1" onClick={this.getNewQuestion.bind(this)}>{state.question.option_1}</p>
                    <p data-question="option_2" onClick={this.getNewQuestion.bind(this)}>{state.question.option_2}</p>
                    <p data-question="option_3" onClick={this.getNewQuestion.bind(this)}>{state.question.option_3}</p>
                    <p data-question="option_4" onClick={this.getNewQuestion.bind(this)}>{state.question.option_4}</p>
                </div>
            </div>
        );
    }
}   

export default Action;

内部&#34;如果&#34; &#34; getNewQuestion&#34;的声明我想做点什么:

n2.classList.addClass(&#39;隐藏&#39);

我无法弄清楚如何从&#34; Action&#34;访问父节点的dom节点。成分

3 个答案:

答案 0 :(得分:1)

孩子是否真的需要直接访问父DOM?父组件不应该知道如何呈现自己吗?如果是这样,那么您可以使用传递给子节点的回调,以便子节点可以在父节点更改时通知父节点。

const Child = ({modifyParent}) => (
  <div onClick={ modifyParent } >Click me!</div>
);

const Parent = () => {
  const modifyMyOwnStyle = event => {
    // here you have easy access 
    // if you want to style the parent.
    alert('Modifying style, based on child call');
  }

  return (
    <Child modifyParent={ modifyMyOwnStyle }/>
  );
};

ReactDOM.render(<Parent />, document.getElementById('root'));

Runnable JSFiddle演示 here

答案 1 :(得分:0)

您可以获取组件的引用并将其传递给其子代,如下所示:

render() {
  return (
    <div ref={node => this.node = node}>
      <SomeChild parent={this.node} />
    </div>
  )
}

在此处详细了解:https://facebook.github.io/react/docs/refs-and-the-dom.html

但是我必须说这样做通常是一个坏主意,如果你真的需要通过节点,或者如果还有另一种解决方法的话,我会重新考虑。

编辑:正如jonahe的评论所示,你通常可以通过将回调传递给子组件来解决问题,当父组件中需要发生某些事情时你可以触发该组件

答案 2 :(得分:0)

比直接访问父节点的DOM节点更好,您可以使用为您执行此操作的回调道具。

类似的东西:

class Grid extends Component {
  constructor(props) {
    super(props)

    this.accessRandomElement = this.accessRandomElement.bind(this)
  }

  accessRandomElement() {
    // do you thing
  }

  render() {
    this.getRandomQuestion()

    return (
      <section className="game">
        ...
        <Action
          question={this.question}
          onAccessYourRandomElement={this.accessRandomElement}
          ///
        />
      </section>
    )
  }
}

然后从Action内部调用this.props.onAccessYourRandomElement()