Ошибка использования ссылок в React 0.14.8

Я работаю над извлечением кода из своего приложения в пакет с открытым исходным кодом. И мое приложение, и мой пакет зависят от одной и той же версии React, 0.14.8.

С тех пор, как я переместил код в пакет (и внес некоторые изменения в код), я не смог отрендерить компонент, использующий refs. Я часами искал совет, и он дал два основных совета:

  1. Убедитесь, что версии реакции не конфликтуют
  2. Убедитесь, что компонент с refs создан в методе рендеринга другого компонента.

Насколько я могу судить, я удовлетворил обоим критериям.

class RangeQuery extends React.Component {
  static propTypes = {
    header: PropTypes.object.isRequired,
    onQueryChange: PropTypes.func.isRequired
  }

  handleChange(ev) {
    const { header } = this.props

    const start = _.isEmpty(this.refs.start.value) ? null : this.refs.start.value
    const end = _.isEmpty(this.refs.end.value) ? null : this.refs.end.value

    const values = typeof(header.query.format) === 'function' ?
      [header.query.fmtValue(start), header.query.fmtValue(end)] :
      [start, end]

    this.props.onQueryChange(header.field, header.query, values)
  }

  render() {
    return (
      <div>
        <input className="form-control" type="text" ref="start" onChange={::this.handleChange} placeholder="min" />
        <input className="form-control" type="text" ref="end"   onChange={::this.handleChange} placeholder="max" />
      </div>
    )
  }
}

const components = {
  like: LikeQuery,
  eq: EqQuery,
  range: RangeQuery
}

export default class HeaderQuery extends React.Component {
  static propTypes = {
    header: PropTypes.object.isRequired,
    onQueryChange: PropTypes.func.isRequired
  }

  render() {
    const { header, onQueryChange } = this.props
    const Query = components[header.query.type] || NoQuery

    return (
      <Query header={header} query={header.query} onQueryChange={this.props.onQueryChange} />
    )
  }
}

Когда я пытаюсь загрузить страницу с этим компонентом, я получаю сообщение об ошибке:

invariant.js: 39 Неперехваченное нарушение инварианта: addComponentAsRefTo (...): ссылки могут быть только у ReactOwner. Возможно, вы добавляете ссылку на компонент, который не был создан внутри метода render компонента, или у вас загружено несколько копий React

Он отображается, если я удалю refs= из тегов input, но они мне, очевидно, нужны.

Я рассмотрел альтернативу написанию редуктора для управления состоянием этих компонентов, но это тяжелая работа для того, что должно работать.

Как я могу исправить свои ссылки, чтобы они работали правильно?

Обновить

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

sam@sam-macbook-ubuntu:~/myProject/client$ npm ls | grep react
├─┬ [email protected]
│ ├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ └─┬ [email protected]
├─┬ [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├─┬ [email protected]
├─┬ [email protected]
│ ├── [email protected]
├── [email protected]
├─┬ [email protected]
│ └── [email protected]
│ ├─┬ [email protected]
│ ├─┬ [email protected]
│ └── [email protected]
│ └── [email protected]

person Samo    schedule 06.04.2016    source источник
comment
Вы уверены, что у вас есть только одна копия React? Это все еще наиболее вероятная причина этой ошибки. npm ls обычно может помочь.   -  person Sophie Alpert    schedule 07.04.2016
comment
Если я не слепой, npm ls выглядит нормально. Вопрос обновлен с результатами.   -  person Samo    schedule 13.04.2016
comment
Да, мне это тоже нравится. Только другая распространенная причина, о которой я знаю, требует разных случаев (например: require('react') vs require('React')), но, поскольку вы используете Ubuntu, я предполагаю, что у вас есть файловая система с учетом регистра, поэтому это вообще не будет работать. Я в тупике без подробностей.   -  person Sophie Alpert    schedule 13.04.2016
comment
Это может быть одна из ваших зависимостей npm, которая импортирует React и использует webpack для сборки. В любом случае, это моя ситуация, и я еще не знаю, как ее разрешить.   -  person donnapep    schedule 13.07.2016
comment
@donnapep: Думаю, вы правы, я все больше и больше осознавал, что его конструкция меняет все.   -  person Samo    schedule 14.07.2016


Ответы (3)


Непонятно, в чем проблема, и это все еще звучит как дублированные копии React, но одним из способов решения проблемы было бы использование стиля ссылки на функцию, который в любом случае будет предпочтительным стилем в будущем:

<input ref={(node) => this.startInput = node} />

Затем вы можете получить доступ к this.startInput.value.

person Sophie Alpert    schedule 07.04.2016
comment
Спасибо, я проверю это. Я стал нетерпеливым и написал логику редуктора для управления компонентом, но если это сработает, это будет очень полезно знать. - person Samo; 07.04.2016

Вы пробовали что-то подобное:

  import ReactDOM from 'react-dom'
const start = _.isEmpty(ReactDOM.findDOMNode(this.refs.start).value) ? null : ReactDOM.findDOMNode(this.refs.start).value
    const end = _.isEmpty(ReactDOM.findDOMNode(this.refs.end).value) ? null : ReactDOM.findDOMNode(this.refs.end).value

Я беру ваш класс, и ваши ссылки работают, я провожу этот простой тест:

import React, { PropTypes, Component } from 'react'
import _ from 'lodash'

export default class RangeQuery extends React.Component {


    handleChange(ev) {


        const start = _.isEmpty(this.refs.start.value) ? null : this.refs.start.value
        const end = _.isEmpty(this.refs.end.value) ? null : this.refs.end.value
        console.log("start")
        console.log(start)


        console.log("end")
        console.log(end)
    }

    render() {
        return (
            <div>
                <input className="form-control" type="text" ref="start" onChange={::this.handleChange} placeholder="min" />
                <input className="form-control" type="text" ref="end"   onChange={::this.handleChange} placeholder="max" />
            </div>
        )
    }
}

Единственная разница в том, что я добавил: export default перед тем, как класс скажет мне, поможет ли это.

person fandro    schedule 06.04.2016
comment
Код в этом обработчике не имеет значения. Просто наличия refs= в тегах input достаточно, чтобы вызвать ошибку. - person Samo; 07.04.2016

это определенно сработает

ReactDOM.findDOMNode(this.refs.start).value;
person nirav jobanputra    schedule 11.04.2016