typescript 如何添加右键菜单以React表行,并访问其属性?

vdgimpew  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(182)

我已经添加了React表包到我的项目,一切都很好,但我也希望有一个可能性,右键单击一行,并执行一些操作(取消,暂停等)。我正在使用React with Typescript,但我希望它不会增加任何复杂性。
我最初的想法是使用react-contextify,但是我找不到任何将react-table和react-contextify结合在一起的工作示例。
我发现的唯一"有效"的例子是:React Context Menu on react table using react-contexify
我最终没有使用react-contextify,它"有点工作",但我不完全确定这一点,因为我有时会遇到这样的异常:

Uncaught TypeError: Cannot read property 'original' of undefined

我现在的代码是这样的:
一个一个一个一个一个x一个一个二个一个x一个一个三个一个x一个一个x一个四个一个
在react-table中添加一个上下文菜单,这样我就可以使用被点击行的属性,最好(也是最简单)的方法是什么?我非常喜欢react-contextify,但是还没有找到任何例子。
谢谢

mspsb9vt

mspsb9vt1#

React钩示例on dev.to
基于类的组件示例on codepen

class App extends React.Component {
  constructor() {
    super();

    this.state = {
      value: ''
    };
  }

  render() {
    return(
      <div>
        {
          ['row1', 'row2', 'row3'].map((row) => {
            return (
              <ContextMenu
                key={row}
                buttons={[
                  { label: 'Editovat', onClick: (e) => alert(`Editace ${row}`) },
                  { label: 'Smazat', onClick: (e) => alert(`Mažu ${row}`) }
                ]}
              >
                <div className="row">{row}</div>
              </ContextMenu>
            );
          })
        }
      </div>
    );
  }
}

class ContextMenu extends React.Component {
  static defaultProps = {
    buttons: []
  };

  constructor() {
    super();

    this.state = {
      open: false
    };
  }

  componentDidMount() {
    document.addEventListener('click', this.handleClickOutside);
    document.addEventListener('contextmenu', this.handleRightClickOutside);
  }

  handleClickOutside = (e) => { 
    if (!this.state.open) {
      return;
    }

    const root = ReactDOM.findDOMNode(this.div);
    const context = ReactDOM.findDOMNode(this.context);
    const isInRow = (!root.contains(e.target) || root.contains(e.target));
    const isInContext = !context.contains(e.target);

    if (isInRow && isInContext) {
      this.setState({
        open: false
      });
    } 
  }

  handleRightClickOutside = (e) => {
    if (!this.state.open) {
      return;
    }

    const root = ReactDOM.findDOMNode(this.div);
    const isInRow = !root.contains(e.target);

    if (isInRow) {
      this.setState({
        open: false
      });
    }
  }

  handleRightClick = (e) => {
    e.preventDefault();
  console.log(e.nativeEvent, window.scrollY);
    this.setState({
      open: true,
      top: window.scrollY + e.nativeEvent.clientY,
      left: e.nativeEvent.clientX,
    });
  }

  render() {
    return (
      <div
        onContextMenu={this.handleRightClick}
        ref={(node) => this.div = node}
      >
        {this.props.children}

        {
          !this.state.open
          ? null
          : <div
              className="context"
              ref={(div) => this.context = div}
              style={{ top: this.state.top, left: this.state.left }}
          >
              <ul>
                {
                  // button - name, onClick, label
                  this.props.buttons.length > 0 &&
                  this.props.buttons.map((button) => {
                    return <li key={button.label}>
                      <a href="#" onClick={button.onClick}>
                        {button.label}
                      </a>
                    </li>
                  })
                }
              </ul>
          </div>
        }
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

相关问题