【问题标题】:React - Triggering a component method from another component, both belonging in the same render()React - 从另一个组件触发组件方法,两者都属于同一个 render()
【发布时间】:2017-07-08 11:25:31
【问题描述】:

我有一个自定义组件Foo,我想从外部触发其'bar'函数:

class Foo extends React.Component {
   bar() { ... }
}

我正在渲染Foo 和一个button,其目的是触发Foo.bar()

render() {

 return (
     <Foo ...>
     </Foo>
     <Button onClick={I want to trigger Foo.bar()} />
 );
}

我尝试过的事情:

  1. &lt;Button &gt; 移动到Foo 中,然后在&lt;Button/&gt; 中添加onClickFoo's 构造函数——onClick 的绑定不起作用——我看到它附加了,但&lt;Button /&gt; 仍然有效不触发onClick。 (或者,如果它可以工作,如何正确地做到这一点)?

不符合我要求的解决方案:

  1. 我看到一个potential solution 建议在整个MyComponent 中收听一次点击,然后进行一些DOM 查询以查找是否点击了实际按钮。但是,这对我不起作用,因为MyComponent 确实拥有这些按钮(这些按钮不是MyComponent.props.children),我更愿意集思广益一个不会强迫我的解决方案必须移动里面的按钮。

  2. Another potential solution 不起作用:我不能让render()&lt;MyComponent /&gt; 的值返回到var myComp,然后在&lt;Button onClick={() =&gt; {myComp.blah()}} /&gt; 内部,因为&lt;Button /&gt; 本身在@987654346 内部实例化@ 作为一个孩子! (而且,它们都在同一个 render() 调用中)

  3. Part b) #2(上),使用 React-Component 静态类方法,也不起作用:我需要在每个实例的基础上使用它。

  4. Using app state (such as a store) 也不是我想要的——MyComponent 是一个可重复使用的小部件,不能绑定到特定的应用程序状态或监听任何特定的存储或存储操作。

有什么建议吗?

谢谢

【问题讨论】:

  • 你可以去github.com/burakozturk16/pigeon看看

标签: javascript reactjs dynamic


【解决方案1】:

您可以在父级上定义一个函数,该函数具有对 Foo 子级的引用。这个函数会调用 this.refs.foo.yourFunction();然后将该函数传递给按钮,以便在单击按钮时调用父函数。在此处添加了一个示例,单击按钮将切换 Foo 组件的状态(但它可以做任何事情)。

以下示例

class Parent extends React.Component {
  triggerFoo() {
    this.foo.toggle();
  }
  render() {
    return (
      <div>
        <Foo ref={foo => this.foo = foo} />
        <Button onClick={this.triggerFoo.bind(this)}/>
      </div>
    );  
  }
}

class Foo extends React.Component {
  state = {foo: false}
  toggle() {
    this.setState({
      foo: !this.state.foo
    });
  }
  render() {
    return (
      <div>
        Foo Triggered: {this.state.foo.toString()}
      </div>
    );
  }
}


class Button extends React.Component {
  render() {
    return (
      <button onClick={this.props.onClick}>
        Click This
      </button>
    );
  };
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root" />

【讨论】:

  • 是的,这会很有效。非常感谢您的明确解释和建议:)
  • 快速说明:最新的 React 版本似乎不支持“字符串”引用?根据最新的反应文档(2017 年 2 月), ref 现在接受一个回调,该回调将元素作为第一个参数。所以你的上面将是 ref={(foo) => {this.foo = foo}} (我实际上使用旧版 ref api 得到了一个硬不变量违规,但使用回调模式解决了这个问题)
  • 是的,这是个好主意。字符串引用仍然适用于一般情况,但取决于您的代码的结构和“this”的绑定方式,它似乎会导致问题。我更新了答案以反映使用 ref 的回调。
  • 我在 refs 上搜索了所有内容,这是最好的例子。 ty
  • 这个答案真的很有帮助:) @noveyak
【解决方案2】:

2020 年更新

这就是使用功能组件和 TS 的方法

  1. 发送 setCustomRefCustomComponent 并向下发送到 CustomButton 以设置 customRef
  2. 发送 customRefClickDiv
  3. 调用 customRef.click();在 ClickDiv

CSBhttps://codesandbox.io/s/triggering-component-method-from-another-component-skt8o?file=/src/App.tsx

Above Codesandbox 并不总是有效,但我注意到它在一段时间后开始工作。

import React from "react";
import "./styles.css";
import Button, { ButtonProps } from "@material-ui/core/Button";

export default function App() {
  const [customRef, setCustomRef] = React.useState<HTMLButtonElement | null>(
    null
  );
  return (
    <div className="App">
      <h3>
        React - Triggering a component method from another component, both
        belonging in the same render()
      </h3>
      <p>
        <ClickDiv customRef={customRef} />
      </p>
      <CustomComponent setCustomRef={setCustomRef} />
    </div>
  );
}

type Props = {
  setCustomRef: React.Dispatch<React.SetStateAction<HTMLButtonElement | null>>;
};

const CustomComponent = ({ setCustomRef }: Props) => {
  const anchorRef = React.useRef<HTMLButtonElement>(null);
  const { current } = anchorRef;
  React.useEffect(() => {
    if (current) {
      setCustomRef(current);
    }
  }, [current, setCustomRef]);

  return <CustomButton ref={anchorRef}>Custom Button</CustomButton>;
};

const CustomButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
  (props, ref) => {
    const onClick = () => {
      alert("CustomButton clicked");
    };
    return (
      <Button ref={ref} {...props} variant="contained" onClick={onClick} />
    );
  }
);

type ClickDivProps = {
  customRef: HTMLButtonElement | null;
};
const ClickDiv = ({ customRef }: ClickDivProps) => {
  const onClick = () => {
    if (customRef) customRef.click();
  };
  return <button onClick={onClick}>Triger Custom Button Click</button>;
};

【讨论】:

    猜你喜欢
    • 2021-06-15
    • 2017-12-09
    • 2020-12-20
    • 2017-08-19
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多