Reputation: 25
I'm working on an editor in which I'd like to have a context menu (an anchored menu, not a pop-up) that changes depending upon the selected item: e.g. when I'm editing item one, I get the context menu for item one, and when I'm editing item two, I get the context menu for item two.
+----------+ +------------------+
| | | Item One |
| Editor | +------------------+
| Menu | +------------------+
| | | Item Two |
+----------+ +------------------+
I'm not sure what the most React-y way to do this would be. My instinct would be to have a component hierarchy like this (describing children):
EditorInterface
- [EditableOne, EditableTwo, ...]
- ContextMenu
and then pass an onFocus
callback to EditableOne
et al., but then I'm not sure how to update the EditorMenu
component based on that. Maybe this isn't the right way to go about this at all.
The EditorMenu
component needs to be able to talk to the Item
components as well (to signal changes), which suggests that the EditorMenu
should be a child component of the Item
(since all the state associated with aforementioned Item
should be maintained in the Item
and solely there).
Tips appreciated!
Upvotes: 1
Views: 1692
Reputation: 2316
When you are developing in React, the Parent
will control its Child
, so you should always be lifting your state up. Also, take a look at thinking in React, it might help with architecting your React app.
Your hierarchy should look like this:
import React, {Component} from "react";
class EditorInterface extends Component {
state = {
focusedItem: 0
}
handleItemFocus = item =>
this.setState({focusedItem: item});
render() {
return (
<div>
<ContextMenu focusedItem={this.state.focusedItem} />
<EditableOne onItemFocus={this.handleItemFocus} />
<EditableTwo onItemFocus={this.handleItemFocus} />
</div>
);
}
}
const ContextMenu = ({ focusedItem }) =>
focusedItem === 1 ? (
<div>
<span>Context Menu for Item 1</span>
</div>
) : focusedItem === 2 ? (
<div>
<span>Context Menu for Item 2</span>
</div>
) : (
<div>
<span>No item is focused</span>
</div>
);
const EditableOne = ({onItemFocus}) => (
<input type="text" onFocus={() => onItemFocus(1)} />
)
const EditableTwo = ({onItemFocus}) => (
<input type="text" onFocus={() => onItemFocus(2)} />
)
Upvotes: 1