score:11

Accepted answer

You need to lift your state up in your situation. The second option is what @Gavin Thomas suggested in the comment. But without Redux you can do it like:

const InputArea = (props) => {
  const handleChange = (e) => props.handleInputValue(e.target.value);

  return (
    <div className="column">
      <div className="col-body">
        <textarea
          id="editor"
          placeholder="Enter text here"
          onChange={handleChange}
        ></textarea>
      </div>
    </div>
  );
};

const DisplayArea = (props) => (
  <div className="column">
    <div className="col-body">
      <div id="preview">{props.inputValue}</div>
    </div>
  </div>
);

class App extends React.Component {
  state = {
    inputValue: "Initial Value",
  };

  handleInputValue = (inputValue) => this.setState({ inputValue });

  render() {
    return (
      <div id="wrapper" className="App">
        <DisplayArea inputValue={this.state.inputValue} />
        <InputArea handleInputValue={this.handleInputValue} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

Here, we hold our input value state in the parent component, which is App. We pass a callback function to InputArea and change our parent component's state using this callback function. Then we pass this state to our DisplayArea component.

score:3

Here are the relevant parts of the code. Basically passing a liftState method to the InputArea component which will actually update the state of App when called. Then pass content to DisplayArea as a prop.

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            content: ""
        };
    }
    liftState = state => {
        this.setState(state);
    }
    render() {
        return (
            <div className="App">
                <InputArea liftState={this.liftState}/>
                <DisplayArea content={this.state.content}/>
            </div>
        );
    }
}

class InputArea extends Component {
    handleChange(event) {
        this.props.liftState({content: event.target.value});
    }
}

class DisplayArea extends Component {
    render() {
        return (
            <div className="column">
                <div className="col-body">
                    <div id="preview">{this.props.content}</div>
                </div>
            </div>
        )
    }
}

score:3

The React.js documentation says (Lifting State Up):

Often, several components need to reflect the same changing data. We recommend lifting the shared state up to their closest common ancestor...

Example:

// Parent component which contains shared state
class Parent extends Component {
  constructor(props) {
    super(props);

    this.state = {
      child1Value: 0,
      child2Value: 0,
    }

    this.handleChild1Click = this.handleChild1Click.bind(this);
    this.handleChild2Click = this.handleChild2Click.bind(this);
  }

  handleChild1Click(nextValue) {
    this.setState({ child1Value: nextValue });
  }

  handleChild2Click(nextValue) {
    this.setState({ child2Value: nextValue });
  }

  render() {
    return (
      <div>
        <Child
          value={this.state.child2Value}
          onClick={this.handleChild1Click}
        />
        <Child
          value={this.state.child1Value}
          onClick={this.handleChild2Click}
        />
      </div>
    )
  }
}


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

    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.onClick(this.props.value + 1);
  }

  render() {
    return (
      <div>
        <p>Value of my sibling: {this.props.value}</p>
        <button onClick={this.onClick}></button>
      </div>
    )
  }
}

Related Query

More Query from same tag