Подтвердить что ты не робот

Как получить доступ к функциям дочерних компонентов через ссылки

В документах для React указано, что функции компонента могут быть доступны родительским компонентом через refs. См.: https://facebook.github.io/react/tips/expose-component-functions.html

Я пытаюсь использовать это в своем приложении, но при вызове дочерней функции запускается ошибка "undefined is not a function". Мне интересно, не связано ли это с использованием формата ES6 для классов React, потому что я не вижу других различий между моим кодом и документами.

У меня есть компонент Dialog, который выглядит как следующий псевдокод. Диалог имеет кнопку "Сохранить", которая вызывает функцию save(), которая должна вызвать функцию save() в дочернем компоненте Content. Компонент Content собирает информацию из полей дочерней формы и выполняет сохранение.

class MyDialog extends React.Component {
  save() {
    this.refs.content.save();                    <-- save() is undefined
  }

  render() {
    return (
      <Dialog action={this.save.bind(this)}>
        <Content ref="content"/>
      </Dialog>);
   }
}

class Content extends React.Component {
  save() {
    // Get values from child fields
    // and save the content
  }
}

Вместо этого я мог бы передать prop (saveOnNextUpdate) до Content и затем выполнить сохранение, когда это правда, но я бы предпочел выяснить, как получить описанный выше метод в React doc выше.

Любые идеи о том, как заставить doc-подход работать или обращаться к дочерней компонентной функции по-другому?

4b9b3361

Ответ 1

Как оказалось, m90 был прав - это совсем другая проблема. Я отправляю решение на случай, если кто-то столкнется с той же проблемой в будущем.

Мое приложение построено с помощью Redux, и проблема связана с использованием функции connect-redux connect для подключения компонента к хранилищу/глобальному состоянию. По какой-то причине экспорт компонента и подключение его к хранилищу делает невозможным доступ к функциям внутри него. Чтобы обойти это, мне пришлось удалить все использование глобального состояния из Content, чтобы я мог экспортировать его как "немой" компонент.

Чтобы быть более понятным, Content.js выглядел так:

var connect = require('react-redux').connect;

class Content extends React.Component {
  save() {
    // Get values from child fields
    // and save the content

    // Use of this.props.stateObject
  }
}

function mapStateToProps(state) {
  const {
    stateObject
  } = state;

  return {
    stateObject
  };
}

module.exports = connect(mapStateToProps)(Content);

Удаление использования глобального состояния (и, следовательно, использование connect и mapStateToProps позволило мне экспортировать компонент, используя:

module.exports = Content;

Доступ к this.refs.content.save() магически сработал после этого.

Ответ 2

Redux connect принимает параметр параметра в качестве четвертого параметра. В этом параметре параметра вы можете установить флаг withRef в значение true. Затем вы можете получить доступ к функциям refs, используя getWrappedInstance(). Вот так:

class MyDialog extends React.Component {
  save() {
    this.refs.content.getWrappedInstance().save();
  }

  render() {
    return (
      <Dialog action={this.save.bind(this)}>
        <Content ref="content"/>
      </Dialog>);
   }
}

class Content extends React.Component {
  save() { ... }
}

function mapStateToProps(state) { ... }

module.exports = connect(mapStateToProps, null, null, { withRef: true })(Content);

Подробнее об этом читайте здесь: https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

Стоит прочитать эту статью об использовании ссылок и рассмотреть, если лучше подходит: https://facebook.github.io/react/docs/refs-and-the-dom.html#dont-overuse-refs

Ответ 3

Альтернативный способ сделать это - использовать какое-либо другое имя (кроме ref). Я обнаружил, что это также хорошо работает, если вы используете библиотеку, такую как styled-components или emotion Например, в подключенном MyComponent:

<MyComponent
  ...
  innerRef={(node) => { this.myRef = node; }}
/>