Travis DePrato
Travis DePrato

Reputation: 25

Changing Context Menu in React Based on Selected Component

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

Answers (1)

Tiago Alves
Tiago Alves

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

Related Questions