Reputation: 17332
There is a main component, which uses a menu component. The menu component is using a state property to save the information about selected menu item. But now I need to get the selected module in the main component. How do I do that?
class Main extends Component {
doSomething(module) {
console.log(module) // should get 'targetValue'
// I need to get the info, which module is selected.
// This info is stored as a state value in the `MainMenu` Component
// How do I get this information? I can't use the parameter `selectModule` as it is done here.
}
render() {
return (
<div>
<MainMenu />
<Button
onClick={ this.doSomething.bind(this, selectedModule) }
/>
</div>
)
}
}
In this component a menu is generated for each module (of modules
array). By clicking on one item, this module is stored into module
state variable.
class MainMenu extends Component {
constructor(props) {
super(props)
this.state = {
module: 'initialValue'
}
}
selectModule(module) {
this.setState({ module })
}
render() {
return (
<Menu>
<Menu.Item onClick={ this.selectModule.bind(this, 'targetValue') } >
{ title }
</Menu.Item>
</Menu>
)
}
}
Upvotes: 0
Views: 3068
Reputation: 8922
Sharing state with react is sometimes a bit hard.
The react philosophy tends to say that we have to manage state from top to bottom. The idea is to modify the state in your parent, and pass the informations as props. For example, let's imagine the following scenario :
class Main extends React.Component {
contructor(props) {
super(props);
this.state = { currentMenuSelected: 'Home' };
}
onPageChange(newPage) {
this.setState({ currentMenuSelected: newPage });
}
render() {
return(
<div>
<AnotherComponent currentMenu={this.state.currentMenuSelected} />
<MenuWrapper onMenuPress={this.onPageChange} />
</div>
)
}
}
In my example, we tell the MenuWrapper
to use the Main.onPageChange
when changing page. This way, we're now able to pass that current selected menu to AnotherComponent
using props.
This is the first way to manage state sharing using react, and the default one provided by the library
If you want to manage more complex stuff, sharing more state, you should take a look at the flux architecture https://facebook.github.io/flux/docs/overview.html
and the most common implementation of flux : http://redux.js.org/
Upvotes: 0
Reputation: 104369
Instead on maintaining the state
in MainMenu component, maintain in parent component Main, and pass the module value in props
, also pass a function
to MainMenu to update the state
of parent component Main from child MainMenu.
Write it like this:
class Main extends Component {
constructor(props) {
super(props)
this.state = {
module: 'initialValue'
}
this.update = this.update.bind(this);
}
update(value){
this.setState({
module: value
});
}
doSomething(){
console.log(this.state.module);
}
render() {
return (
<div>
<MainMenu module={this.state.module} update={this.update}/>
<Button
onClick={ this.doSomething.bind(this) }
/>
</div>
)
}
}
class MainMenu extends Component {
selectModule(module) {
this.props.update(module);
}
render() {
console.log(this.props.module);
return (
<Menu>
<Menu.Item onClick={this.selectModule.bind(this, 'targetValue') } >
{ title }
</Menu.Item>
</Menu>
)
}
}
Upvotes: 1
Reputation: 22862
Instead of doing some magic and examining internal state if children components lift the state to parent. Child becomes stateless.
class Main extends Component {
state = {
module: 'initialValue'
}
setActiveModule = (module) => {
this.setState({ module })
}
render() {
return (
<MainMenu onChange={this.setActiveModule} />
)
}
}
class MainMenu extends Component {
onClick = (module) => () => {
this.props.onChange(module)
}
render() {
return (
<Menu>
<Menu.Item onClick={this.onClick(title)} >
{title}
</Menu.Item>
</Menu>
)
}
}
Upvotes: 1
Reputation: 4228
Store the menu state in the main component, and pass the state updater down to the menu.
This is quite helpful in getting into top-down state https://facebook.github.io/react/docs/thinking-in-react.html
Upvotes: -1