2017-02-22 12 views
6

Допустим, у меня есть карта, которая содержит регистрационную формуРеагировать доступа Dom Узлов из this.props.children

<Card> 
    <LoginForm/> 
</Card> 

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

<Form > 
    <input type="text" name="email"/> 
    <input type="password" name="password"/> 
    <input type="submit"/> 
</Form> 

Потому, что я бы хотел сделать, это оказать submitbutton не в props.children контекста, но делают это завернутым за пределами данного ребенка!

render() { 
return (
    <div className="card"> 
     <div className="inner"> 
     {/* render Children */} 
     {this.props.children != undefined ? 
      <div className="childrenWrapper"> 
      {this.props.children} 
      </div> 
      : "" 
     } 
     </div> 
     {/* render submit from login form here, not above */ 
    </div>) 

example expected result

Есть некоторые компоненты, которые на самом деле делать то, что я хочу. Например, компонент Tabs от react-toolbox. Они каким-то образом удается вынести то, что внутри вкладки (детей) где-то еще

Просто, например

<Tabs index={this.state.inverseIndex} onChange={this.handleInverseTabChange} inverse> 
     <Tab label='First'><small>First Content</small></Tab> 
     <Tab label='Second'><small>Second Content</small></Tab> 
     <Tab label='Third'><small>Third Content</small></Tab> 
     <Tab label='Disabled' disabled><small>Disabled Content</small></Tab> 
    </Tabs> 

что приведет к следующему HTML rendered html example

Как вы можете видеть детей на вкладке где отображается в их собственном разделе Я не хочу ничего менять в форме для решения этой проблемы, я хотел бы передать форму на Карту и позволить Карте решить, как Форма будет отображаться в функции рендеринга карты.

Поскольку я пытаюсь реализовать Карту дизайна материалов Google component и просто использую его в качестве шаблона, появляется больше элементов, которые нужно разделить и разместить в тех позициях, которые я хочу, чтобы они были. Дело в том, что я могу разместить соответствующий HTML-код вокруг Формы, чтобы получить его как карту, которую я хочу, но тогда мне вообще не нужен компонент.

+0

Как насчет того, чтобы установить переменную с помощью flatButton, а затем передать ее в качестве реквизита для компонента карты? Ах, я забыл: для доступа к flatButton, я думаю, вы могли бы использовать ref prop. – dschu

+0

@dschu, который работает, но дело в том, что сама плоская кнопка находится внутри формы, а затем будет отображаться в детской части, а также – TeaTime

+0

Да, вы правы. Вам нужно было бы передать другую опору компоненту LoginForm, чтобы сообщить компоненту не отображать кнопку. В этом случае вам следует рассмотреть возможность реструктуризации ваших компонентов. – dschu

ответ

3

Здесь есть несколько достойных ответов, но никто из них напрямую не отвечает на ваш вопрос. Поэтому, даже если вы должны реорганизовать свой код (излагаемые ниже), я собираюсь предоставить вам рабочее решение:

class Card extends React.Component { 
    constructor() { 
    super(); 
    this.state = {}; 
    } 

    render() { 
    console.log(typeof this.props.children) 
    return (
     <div> 
     {typeof this.props.children === 'object' 
      ? React.cloneElement(this.props.children, { ref: (n) => this.form = n }) 
      : null} 
     <button onClick={(e) => console.log(this.form.data)}>submit</button> 
     </div> 
    ); 
    } 
} 

class Form extends React.Component { 
    constructor() { 
    super(); 
    this.onChange = this.onChange.bind(this); 
    this.state = {}; 
    } 

    onChange(e) { 
    this.data = e.target.value; 
    } 

    render() { 
    return (
     <form> 
     <input type="text" onChange={this.onChange} /> 
     </form> 
    ); 
    } 
} 

ReactDOM.render(
    <Card><Form /></Card>, 
    document.getElementById('container') 
); 

https://jsbin.com/fohehogozo/edit?js,console,output

Установив свойство на экземпляре, вы можете получить доступ, что имущество от детей, используя ref. Я проверил здесь typeof === object, потому что был только один ребенок.

ВНИМАНИЕ: этот код НЕ ПРОИЗВОДИТ ГОТОВ. Никогда не запускайте это на производстве. Код, который я продемонстрировал, - ужасный взлом, и вы никогда не должны пытаться это делать дома.


+0

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

+1

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

0

Если вы пытаетесь отправить форму, возможно, посмотрите на передачу события onChange и сохранение значения (в соответствии с именем поля) в состоянии Карты. Затем присоедините событие onChange на входах, чтобы как только они были обновлены, данные будут переданы обратно в контейнер для отправки.

+0

на самом деле im пытается отобразить часть из класса формы в другом месте в классе карты – TeaTime

+1

Просто из интереса, зачем вам это нужно? Кажется, что это запах кода –

+0

, потому что я хочу отображать форму нормально и, если она используется в стиле карты, по-разному. К сожалению, мне нужно изменить компоновку html, и я не застрял там – TeaTime

0

Если вы хотите разделить прошедшие дочерние элементы, вы можете просто фильтровать массив children, чтобы разделить детей, однако ваши дети, кажется, вложены.

Почему вы не позволяете детям с детьми разделять между вашим контейнером inner и другим контентом?

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

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

-1

Не пытайтесь манипулировать DOM; это, как правило, анти-шаблон в React (хотя есть несколько допустимых вариантов использования). В вашем случае вместо того, чтобы буквально пытаться переместить элементы, я просто спрячу кнопку в форме и добавлю ее в родительский.

Если у вас есть доступ к внутренности <LoginForm>, вы можете добавить опору, чтобы скрыть кнопку:

const button = 
    <div class="flatbuttonWrapper"> 
    <input type="submit"/> 
    </div>; 

<Form> 
    <input type="text" name="email"/> 
    <input type="password" name="password"/> 
    {!this.props.hideButton && button} 
</Form> 

Добавить кнопку в Card компонента:

render() { 
    return (
    <div className="card"> 
     <div className="inner"> 
     {this.props.children != undefined ? 
      <div className="childrenWrapper"> 
      {this.props.children} 
      </div> 
      : "" 
     } 
     </div> 
     <div class="flatbuttonWrapper"> 
     <input type="submit"/> 
     </div> 
    </div> 
); 
} 

Наконец, в вашем родитель:

<Card> 
    <LoginForm hideButton /> 
</Card> 

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