Tzury Bar Yochay Tzury Bar Yochay - 15 days ago 9
Javascript Question

Is It Possible To Trigger Contained Component's render from within the Container in React?

So I got

App
which implements a
componentDidMount
and
render
.

App contains 2 components, one, an
AutoComplete
input, and the other is a
CardView
.

The plans is that once a user have chosen an item from the
AutoComplete
list, to display it in the
CardView


I wonder how would I trigger
CardView
's render (i.e. setting it's state) from within the
AutoComplete
event handler.

See the line that reads:

// willing to trigger CardView's render right here.

In the code below.

import React, { Component } from 'react';
import injectTapEventPlugin from 'react-tap-event-plugin';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AutoComplete from 'material-ui/AutoComplete';


// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

import './App.css';


class App extends Component {
constructor () {
super();
this.state = {accounts: []}
this.showAccount = this.showAccount.bind(this);
}

componentDidMount() {
this.setState({ accounts: [
{account_name: "foo", account_id: 1},
{account_name: "bar", account_id: 2}
]})
}

showAccount (value) {
// willing to trigger CardView's render right here.
}

render() {
return (
<MuiThemeProvider>
<div className="App">
<center>
<AutoComplete
floatingLabelText="account name"
filter={AutoComplete.caseInsensitiveFilter}
dataSource={this.state.accounts.map((account) => account.account_name)}
onUpdateInput={this.showAccount}
/></center>
<CardView />
</div>
</MuiThemeProvider>
);
}
}

export default App;

Answer

Here is my answer based on how I understand your question.

  class App extends Component {
  constructor () {
    super();
    this.state = {accounts: [], infoToDisplay: ''}
    this.showAccount = this.showAccount.bind(this);
  }

  componentDidMount() {
    this.setState({ accounts: [
      {account_name: "foo", account_id: 1},
      {account_name: "bar", account_id: 2}
    ]})
  }

  showAccount (value) {
    let infoToDisplay = this.state.infoToDisplay;
    infoToDisplay = value;
    this.setState({infoToDisplay}); 
    // this line will cause a rerender after the user has chosen something
    // from the autoComplete list
  }

  render() {
    return (      
      <MuiThemeProvider>
        <div className="App">
        <center>
        <AutoComplete
          floatingLabelText="account name"
          filter={AutoComplete.caseInsensitiveFilter}
          dataSource={this.state.accounts.map((account) => account.account_name)}
          onUpdateInput={this.showAccount}
        /></center>
        <CardView accounts={this.state.infoToDisplay} /> 
        </div>
      </MuiThemeProvider>
    );
  }
}

export default App;

what I have done, is give the app component state to keep track of the user's selection. I then pass this state as props to the card component. When the state is full card will show it, so in the showAccount function i call setState on infoToDisplay which causes another render, now the card's props will be full with the latest info and display it.

Hope this is clear.