【问题标题】:How does one React component call a method in another React component?一个 React 组件如何调用另一个 React 组件中的方法?
【发布时间】:2017-12-09 21:28:24
【问题描述】:

我的页面包含两个完全独立的 React 组件(不同的文件、不同的类、没有父子关系)。

一个组件如何调用另一个组件中的实例方法?问题似乎是获取目标组件的实例。

编辑:两个组件共享同一个父组件(即它们以相同的render() 方法呈现)但我仍然不知道如何将目标组件的引用传递给调用组件。

【问题讨论】:

  • 这是反应中的反模式,建议将方法放在包含组件(每个组件的父组件)中,然后作为道具传递给它们。或者,您可以创建具有此功能的高阶组件,并使用它“增强”这两个组件

标签: reactjs


【解决方案1】:

简短的回答是:他们没有。

不清楚你想要完成什么,所以我不能谈论你的具体情况,但 React 组件相互“通信”的方式是通过 state 和 props。例如,考虑一个有两个子组件CompACompBPage 组件,渲染如下:

<Page>
    <CompA />
    <CompB />
</Page>

如果CompA 需要向CompB 传递一些东西,这是通过Page 组件上的状态来完成的,该状态作为CompACompB 上的道具公开,如下所示:

class Page extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            sharedValue: 42,
        };
    }

    onChangeSharedValue(newValue) {
        this.setState({ sharedValue: newValue });
    }

    render() {
        return (
            <div>
                <CompA
                    sharedValue={this.state.sharedValue}
                    onChange={this.onChangeSharedValue}
                />
                <CompB
                    sharedValue={this.state.sharedValue}
                    onChange={this.onChangeSharedValue}
                />
            </div>
        );
    }
}

如果CompA 需要更改共享值,它会调用onChange 处理程序,这将更改Page 组件上的状态。然后该值将向下传播到CompB 组件。

您所描述的组件之间没有直接通信;这一切都是通过 state 和 props 完成的。

【讨论】:

  • 你是对的。我的解决方案是在两个组件中调度相同的操作,而不是试图让它们相互交谈。
【解决方案2】:

“道具下降,事件上升。”

如果您向我们提供您正在寻找的具体示例,我可以用更具体的回复更新此帖子。

但总的来说,您可以采取几种策略。 Some of them are presented here.

首选方法是将调用方法简单地移至父组件。这是 React 中的常用策略。

如果你做不到,那么下一步就是为父组件编写一个事件处理程序,然后将此事件传递给第一个子组件。

使用此事件将信息向上传递给父组件,这样当它被触发时,数据可以作为道具向下传递给第二个组件。

【讨论】:

    【解决方案3】:

    我最近才开始进行 React 开发,并找到了适合我的解决方案。诚然,我没有看到它在任何地方被引用过,当我把它展示给一位从事 React 多年的同事时,他有点皱起眉头,觉得这不“正确”,但他无法真正向我解释为什么它是“错误的”。我敢肯定我会在这里大喊大叫,但我想我还是会分享:

    文件 #1:objects.js

    let objects= {};
    export default objects;
    

    文件 #2:firstComponent.js

    import React from 'react';
    import objects from 'objects';
    
    class FirstComponent extends React.Component {
        constructor(props) {
            super(props);
            objects['FirstComponent'] = this; // store a reference to this component in 'objects'
        }
    
        doSomethingInFirstComponent() {
            console.log('did something in first component');
        }
    
        render() {
            return (<div></div>);
        }
    }
    export default FirstComponent;
    

    文件 #3:secondComponent.js

    import React from 'react';
    import objects from 'objects';
    
    class SecondComponent extends React.Component {
        render() {
            objects.FirstComponent.doSomethingInFirstComponent(); // call the method on the component referred to in 'objects'
            return (<div></div>);
        }
    }
    export default SecondComponent ;
    

    SecondComponent 渲染时,会触发 FirstComponent.doSomethingInFirstComponent() 中的 console.log()。当然,这假设 FirstComponent 实际上是已安装

    我认识的“React Guys”似乎认为这种方法在某种程度上是邪恶的。它使用正常 React 范围之外的简单 JavaScript 对象来维护对我选择存储在那里的任何现有对象的引用。除了他们告诉我“这不是你在 React 中做事的方式”之外,我还没有找到一个很好的解释来解释这将如何破坏或以其他方式破坏我的应用程序。我将它用作 Redux 等大规模过度杀伤状态管理工具的低级替代品。我还使用它来避免必须通过数十层 React 组件向下传递属性,以便最后一层的某些东西可以触发第一层的某些东西。

    这并不是说这种方法没有问题:

    1. 它在通用 objects 对象、旨在将自身引用存储在 objects 中的任何组件以及希望使用这些对象的任何组件之间创建了明显的依赖关系参考。再说一次,使用 any 类型的全局状态管理解决方案会产生类似的依赖关系。
    2. 如果您在尝试从 SecondComponent 中调用 FirstComponent 之前对是否会挂载有任何疑问,这可能是一个糟糕的解决方案。
    3. 我发现仅仅拥有一个 React 组件的reference 并不能让你做 React 组件本机可以做的所有事情。例如,调用 objects.FirstComponent.setState() 是行不通的。您可以调用FirstComponent 中的方法,该方法又可以调用自己的setState(),但不能直接从SecondComponent 中调用FirstComponent 的setState()。坦率地说,我认为这是一件好事。
    4. 但是,您可以直接访问 objects 中引用的组件的状态值。
    5. 这只能通过“全局”组件(功能上用作单例的组件)来完成。例如,如果您有一个名为 BasicSpan 的简单 UI 组件,它只渲染一个基本的 span 标签,然后您继续在整个 React 应用程序中一遍又一遍地使用该组件 /em>,我敢肯定,尝试将对这些简单组件的引用放在 objects 对象中,然后尝试智能地管理对这些组件内部方法的调用,这将很快成为一场难以管理的噩梦。

    【讨论】:

      【解决方案4】:

      您可以将事件作为道具发送并从其他组件调用。

      假设你有一堂课

          Class A{
      
          handleChange(evt)
          {
      
         this.setState({
      name:evt.target.value
      
      })
          }
      
          render{
          return(
          <div>
          <ComponentB name={this.state.name}{ onChange={this.handleChange}/>
      
          </div>
      
          );
          }
          }
      

      组件

       Class B{
      
          handleChange()
          {
      
          //logic
          }
      
          render{
          return(
          <div>
          <input type="text" onChange={this.props.onChange}/>
          {this.props.name}
          </div>
      
          );
      
          }
      
      • 在组件 B 中,当您更改输入时,它将调用该方法 类 A 和更新 A 的状态。
      • 现在在组件 B 中获取更新状态作为道具将为您提供 您刚刚输入的更改文本

      【讨论】:

        猜你喜欢
        • 2016-11-09
        • 2022-08-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多