реагировать на дочерние компоненты без состояния не обновляются при изменении состояния в родительском компоненте

Я создаю небольшое приложение с вкладками, в котором каждая вкладка отображает дочерний компонент.

Я хотел, чтобы на каждой вкладке отображалось разное содержимое, поэтому я создал объект contentTypes вне render(){ .... }, чтобы сопоставить каждую вкладку с соответствующим дочерним компонентом. Дочерние компоненты получают обработчики и состояния через свойства.

class App extends Component {
    state ={
        contentType: "A",
        title: "Overview",
        searchContent: ""
    }

    tabHandler= (content,event)=>{
       console.log("clicked");
       this.setState({
          title: event.target.name,
          contentType: content
       });
    }
    searchHandler = (event) => {

       // this performs a search on a database and 
       //returns suggestions for the current input

       this.setState({
          searchContent: event.target.value
       });
   }  

    contentTypes = {
        A: <A/>,
        B: <B/>,
        C: <C onchange={this.searchHandler.bind(this)} content={this.state.searchContent}/>
    };
    render() {
      return (
        <div className="row">
          <ul>
           <Tab click={this.tabHandler.bind(this)} id="A" name="A"/>
           <Tab click={this.tabHandler.bind(this)} id="B" name="B"/>
           <Tab click={this.tabHandler.bind(this)} id="C" name="C"/>
         </ul>
        <h1 id="title">{this.state.title}</h1>

        {this.contentTypes[this.state.contentType]}

       </div>
     );
   }
}

Дочерние компоненты не имеют состояния и определяются примерно так:

import React from 'react'
import Field from './form-builder/field';

const C = (props) => {

return(

    // Field is another stateless component with formatted <input> tags

    <Field type="text" name="search" content={props.content} onchange={props.onchange}/>
  );
 }

export default C;

Поле определяется следующим образом:

import React from 'react';

const field = (props) => {
    <li className="field">
       <input type="text" onChange={props.onchange} value={props.content} />
       <label htmlFor={props.name}>{props.value}</label>
    </li>
}
export default field;

Проблема в том, что когда я вызываю обработчик изнутри Field для обновления состояния в родительском компоненте (тот, что с render(){ .... }), дочерние компоненты не обновляются с новым состоянием.

Любые идеи о том, как это исправить?


person Hyperspace    schedule 24.05.2018    source источник
comment
Пожалуйста, добавьте также Field   -  person RIYAJ KHAN    schedule 24.05.2018
comment
@RIYAJKHAN добавил   -  person Hyperspace    schedule 24.05.2018


Ответы (1)


Вы определяете contentTypes как свойство класса.
Фактически это то же самое, что:

class App extends Component {
  constructor() {
    this.contentTypes = {
      A: <A />,
      B: <B />,
      C: <C
           onchange={this.searchHandler.bind(this)}
           content={this.state.searchContent}/>
    }
  }
}

Таким образом, элемент отображается в конструкторе и никогда не получает никаких обновлений свойств.
Вот способ исправить это:

class App extends Component {
  contentTypes = {
    A: () => (<A/>),
    B: () => (<B/>),
    C: () => (
        <C
          onchange={this.searchHandler.bind(this)}
          content={this.state.searchContent} />
       )
  }

  // ...

  render () {
    const Content = this.contentTypes[this.state.contentType]

    return (
      <div>
      {/* ... */}
        <Content />
      </div>
    )
  }
}
person DanSnow    schedule 24.05.2018