Reactjs getting a state value from a child component

Viewed 9485

React newbie back here with another question (lol). I have a function that returns a generic component and I was wondering if it's possible to get the state value from that component? Here is what I'm trying to do:

EDIT: I've updated some of my code according to responses

class CreateTable extends Component {
   constructor(props) {
        super(props_;

        this.state = { elements: [] };
    }

    handleCreateTable() {
        var elements = this.state.elements; // []
        elements.push(<TextInput key={"TableName"} label="Table Name" />)'
        elements.push(
                <DataTable
                    tableName = { elements[0].value } // <--- I'd like to do something like this
                />
            );
        this.setState({ elements: elements })
    }
}

TextInput has a child TextField

Thank you for your help!

3 Answers

What I'm trying to do is take some input table name from a user and display it.

The way you could achieve this is by making your TextInput component call a function passed by the parent with the current value of the component.

So your TextInput might look like this:

export default class TextInput extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ""
    };
  }

  handleOnChange = e => {
    const inputText = e.target.value;
    this.setState({
      value: inputText
    });
    this.props.onChange(inputText);
  };

  render() {
    return <input value={this.state.value} onChange={this.handleOnChange} />;
  }
}  

And parent component must pass a function as a prop so that it can know of the changes happening in the child.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tableName: ""
    };
  }
  onInputChange = value => {
    this.setState({
      tableName: value
    });
    console.log("I am Parent component. I got", value, "from my child.");
  };
  render() {
    return (
      <div className="App">
        <TextInput onChange={this.onInputChange} />
        <span>Table:{this.state.tableName}</span>
      </div>
    );
  }
}   

App component is passing onInputChange function to TextInput through onChange prop. Prop name onChange can be anything.

Here is working code sandbox link to test this code.

I have a function that returns a generic component and I was wondering if it's possible to get the state value from that component?

This is not the React way. Instead you should design your components so that the parent keeps all state that it needs. Then the parent passes values from its state as props to its child components.

If a parent component needs to know about events that happen in its children, then you should pass a callback from the parent to the child. Then the child calls this function when an event occurs to notify the parent which can then update its state.

In addition, state should only contain data, not JSX components. You can store a list of data in state and iterate over it in render() to create the necessary components. So for example, if you have a method that calls

this.setState({items: ['foo', 'bar']});

Then in render, you can do something like

return <div>
    {this.state.map(item => <DataTable name={item}/>}
    </div>

It's actually possible, by passing object and setting object attribute in child component

const TextInput = props => {
    let holder = {
        getChildState: null
    };

    return (
        <div>
            <TextBox {...props} type="text" multiline={false} id={generateId()} holder={ holder }/>
        </div>
    );
}

class TextBox extends Component {
  constructor(props) {
    super(props);

    this.state = {
        value: null,
        error: false,
        errorMsg: null,
    };

    this.props.holder.getChildState = () => this.state;
  }

  ....
}

So if your TextInput would be more complex, than you would use holder.getChildState(), but it would be available only after TextBox constructed.

There is also other possibility to use emitter.

But you definitely should be sure what you are doing, because it is more simple and convenient to use only down direction props sharing especially considering that this is react philosophy. If you feel that some component should report its state to few other you may try redux

Related