Як отримати доступ до елемента DOM в React? Що таке еквівалент document.getElementById () в React


204

Як вибрати певні бари у react.js?

Це мій код:

var Progressbar = React.createClass({
    getInitialState: function () {
        return { completed: this.props.completed };
    },
    addPrecent: function (value) {
        this.props.completed += value;
        this.setState({ completed: this.props.completed });
    },

    render: function () {

        var completed = this.props.completed;
        if (completed < 0) { completed = 0 };


        return (...);
    }

Я хочу використовувати цей компонент React:

var App = React.createClass({
    getInitialState: function () {

        return { baction: 'Progress1' };
    },
    handleChange: function (e) {
        var value = e.target.value;
        console.log(value);
        this.setState({ baction: value });
    },
    handleClick10: function (e) {
        console.log('You clicked: ', this.state.baction);
        document.getElementById(this.state.baction).addPrecent(10);
    },
    render: function () {
        return (
            <div class="center">Progress Bars Demo
            <Progressbar completed={25} id="Progress1" />
                <h2 class="center"></h2>
                <Progressbar completed={50} id="Progress2" />
                <h2 class="center"></h2>
                <Progressbar completed={75} id="Progress3" />
                <h2 class="center"></h2>
                <span>
                    <select name='selectbar' id='selectbar' value={this.state.baction} onChange={this.handleChange}>
                        <option value="Progress1">#Progress1</option>
                        <option value="Progress2">#Progress2</option>
                        <option value="Progress3">#Progress3</option>
                    </select>
                    <input type="button" onClick={this.handleClick10} value="+10" />
                    <button>+25</button>
                    <button>-10</button>
                    <button>-25</button>
                </span>
            </div>
        )
    }
});

Я хочу виконати функцію handleClick10 і виконати операцію для вибраної панелі прогресу. Але отриманий результат:

 You clicked:  Progress1
 TypeError: document.getElementById(...) is null

Як вибрати певний Елемент у react.js?

Відповіді:


215

Ви можете зробити це, вказавши ref

EDIT: У взаємодії v16.8.0 з функціональним компонентом, ви можете визначити коефіцієнт ref за допомогою useRef. Зауважте, що коли ви вказуєте посилання на функціональний компонент, вам потрібно скористатися React.forwardRef на ньому, щоб переслати посилання на елемент використання DOM, useImperativeHandleщоб викрити певні функції з функціонального компонента

Наприклад:

const Child1 = React.forwardRef((props, ref) => {
    return <div ref={ref}>Child1</div> 
});

const Child2 = React.forwardRef((props, ref) => {
    const handleClick= () =>{};
    useImperativeHandle(ref,() => ({
       handleClick
    }))
    return <div>Child2</div> 
});
const App = () => {
    const child1 = useRef(null);
    const child2 = useRef(null);

    return (
        <>
           <Child1 ref={child1} />
           <Child1 ref={child1} />
        </>
    )
}

Редагувати:

У React 16.3+ , використовувати React.createRef()для створення реф:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

Для доступу до елемента використовуйте:

const node = this.myRef.current;

DOC для використання React.createRef ()


EDIT

Однак facebook радить проти цього, оскільки рядкові посилання мають деякі проблеми, вважаються спадщиною і, ймовірно, будуть видалені в одному з майбутніх випусків.

З документів:

Legacy API: String Refs

Якщо ви раніше працювали з React, ви, можливо, були знайомі зі старшим API, де атрибут ref є рядком, наприклад "textInput", а до вузла DOM звертається як this.refs.textInput. Ми радимо проти цього, оскільки рядкові рефлекси мають певні проблеми, вважаються застарілими і, ймовірно, будуть видалені в одному з майбутніх випусків. Якщо ви зараз використовуєте this.refs.textInput для доступу до списку, рекомендуємо замість цього шаблон зворотного виклику.

Рекомендований спосіб для React 16.2 та новіших версій - використовувати шаблон зворотного виклику:

<Progressbar completed={25} id="Progress1" ref={(input) => {this.Progress[0] = input }}/>

<h2 class="center"></h2>

<Progressbar completed={50} id="Progress2" ref={(input) => {this.Progress[1] = input }}/>

  <h2 class="center"></h2>

<Progressbar completed={75} id="Progress3" ref={(input) => {this.Progress[2] = input }}/>

DOC для використання зворотного дзвінка


Навіть більш старі версії реагують на визначені реф. За допомогою рядка, як показано нижче

<Progressbar completed={25} id="Progress1" ref="Progress1"/>

    <h2 class="center"></h2>

    <Progressbar completed={50} id="Progress2" ref="Progress2"/>

      <h2 class="center"></h2>

    <Progressbar completed={75} id="Progress3" ref="Progress3"/>

Для того щоб отримати елемент просто зробіть

var object = this.refs.Progress1;

Не забудьте використовувати thisвсередині функціонального блоку стрілки такі:

print = () => {
  var object = this.refs.Progress1;  
}

і так далі...


5
Facebook не радить такому підходу. Дивіться тут facebook.github.io/react/docs/refs-and-the-dom.html
Дмитро

4
@dmitrymar Як я бачу, вищезазначена сторінка написана на v15.4.2 і далі, і я здогадуюсь, цього раніше не було, коли я писав відповідь. У будь-якому разі редагував відповідь правильним підходом
Shubham Khatri

2
@MattSidor, дякую за редагування, ти врятував мені час :-)
Shubham Khatri,

Гм, запитайте, що, якщо я не можу отримати доступ до нього через "це", як, наприклад, якщо потрібний мені компонент - це екземпляр іншого класу? (Тобто ще одна дитина реагує компонент всередині батьківського компонента)
Акша Кишор

@akshaykishore Вам потрібно буде передати цю інформацію за допомогою іншої назви, сказати innerRef, і передати її потрібному компоненту
Shubham

37

Для отримання елемента в ньому reactпотрібно використовувати refі всередині функції, яку ви можете використовуватиReactDOM.findDOMNode метод.

Але те, що мені подобається робити більше, - це зателефонувати прямо в рамках події

<input type="text" ref={ref => this.myTextInput = ref} />

Це хороше посилання, яке допоможе вам розібратися.


2
Це правильний спосіб зробити це. Це додає посилання на елемент об’єкта / класу, до якого ви можете просто скористатися this.myTextInputдля доступу.
Сем Парментер

1
Як я можу це зробити за допомогою динамічно створеного елемента?
Сагар Кодте

Подзвони React.findDOMNodeменіreact__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
Джеймс Поулоз,

@JamesPoulose переконайтеся, що ви не працюєте в суворому режимі, оскільки реакція не дозволить вам використовувати React.findDOMNodeв суворому режимі.
Limpuls

13

Ви можете замінити

document.getElementById(this.state.baction).addPrecent(10);

з

this.refs[this.state.baction].addPrecent(10);


  <Progressbar completed={25} ref="Progress1" id="Progress1"/>

3
Як я можу це зробити за допомогою динамічно створеного елемента?
Сагар Кодте

1

Оскільки React використовує код JSX для створення HTML, ми не можемо посилатися на dom за допомогою методів регулювання, таких як documentment.querySelector або getElementById.

Натомість ми можемо використовувати систему React ref для доступу та маніпулювання Dom, як показано на прикладі нижче:

constructor(props){

    super(props);
    this.imageRef = React.createRef(); // create react ref
}

componentDidMount(){

    **console.log(this.imageRef)** // acessing the attributes of img tag when dom loads
}


render = (props) => {

const {urls,description} = this.props.image;
    return (

            <img
             **ref = {this.imageRef} // assign the ref of img tag here**
             src = {urls.regular} 
             alt = {description}
             />

        );

}

}


1
Це не правда. Ви можете додати ідентифікатор до елемента img, захопити його за допомогою document.getElementById, і в більшості випадків він буде добре працювати. Це може спричинити проблеми / зробити ваш код важче налагоджувати, але react / jsx donlt зробить це так, що ви НЕ МОЖЕТЕ використовувати рідні методи Dom
adam tropp
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.