2016-04-06 7 views
2

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

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

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

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

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 Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's render method, or you have multiple copies of React loaded

Это делает, если я удалить refs= из input тегов, но я, очевидно, нужны те.

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

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

Update

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

[email protected]:~/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] 
+0

Вы очень уверены, что у вас есть только один экземпляр Реагировать? Это, безусловно, самая вероятная причина этой ошибки. 'npm ls' обычно может помочь. –

+0

Если я не ослеп, 'npm ls' выглядит хорошо. Вопрос обновлен с результатами. – Samo

+0

Да, это тоже хорошо.Только другая общая причина, о которой я знаю, требуется в разных случаях (например: 'require ('react')' vs' require ('React') '), но так как вы на Ubuntu, я предполагаю, что у вас есть чувствительная к регистру файловая система, поэтому это не сработало бы вообще. Я в тупике, без каких-либо подробностей. –

ответ

0

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

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

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

+0

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

0

ли вы пытались что-то вроде этого:

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 перед классом скажите мне, если это поможет

+0

Код в этом обработчике не имеет значения. Просто наличие 'refs =' на тегах 'input' достаточно, чтобы вызвать ошибку. – Samo

0

это, безусловно, работать

ReactDOM.findDOMNode(this.refs.start).value;