代码之家  ›  专栏  ›  技术社区  ›  Dal

试图在react中创建特殊的设计模式,但不确定如何实现

  •  0
  • Dal  · 技术社区  · 7 年前

    我有两个相连的组件,它们都需要相同的父级,这样它们就可以相互通信。然而,我想能够渲染他们在任何地方,100%分开。我有一个 jsfiddle 举例说明这个想法,这是一个糟糕的解决方案,因为每当我需要更改传入的道具时,我都会创建一个新的Img组件。但它表明了这个想法。我觉得我可能做错了,但也许有一种方法可以将道具传递给Img,而不需要创建新的实例。将非React类作为父类肯定不是理想的选择。

    小提琴讲解: 制作一个接收道具的Img组件,告诉它是否应该渲染 创建一个开关组件,当单击时,该组件将更改传递到Img组件的道具

    它们可以在任何地方单独呈现,并由父类控制。 forceUpdate只是为了让这个示例工作,我知道这不是一个很好的用途。

    代码:

    const Img = (props) => {
    
      return (
        <div><img style={{ display: props.isShowing ? 'inline' : 'none', width: '100px' }} src="http://blog.nationalgeographic.org/wp-content/uploads/2010/04/Greatest-Nature-Photographs-of-All-Time-3.jpg" /></div>
      );
    };
    
    const Switch = (props) => {
    
      return (
        <div style={{ width: '50px', height: '50px', background: 'black', color: 'white'}} onClick={() => props.toggleImg()}>
        click me
        </div>
      );
    };
    
    class MasterComponent {
      constructor(outerThis) {
        this.outerThis = outerThis;
        this.toggleState = true;
        this.img = <Img isShowing={ true } />;
        this.switch = <Switch toggleImg={ () => this.toggleImg() } />;
      }
    
      toggleImg() {
        this.toggleState = !this.toggleState;
        this.img = <Img isShowing={ this.toggleState } />;
        this.outerThis.forceUpdate();
      }
    
    }
    
    
    class Example extends React.Component {
        constructor(props) {
            super(props);
        this.masterComponent = new MasterComponent(this);
      }
    
      render() {
        return <div>
        {this.masterComponent.img}
        {this.masterComponent.switch}
        </div>;
      }
    }
    

    编辑: 所以问题基本上是这样的。我希望“MasterComponent”是某种父级,它为您提供两个子级,它们在状态/道具领域中相互交互,但像示例中的渲染一样单独渲染。因此,想象一下导入MasterComponent,然后像我在示例组件中所做的那样使用它,而不知道幕后发生了什么。这是我所希望的设计模式,但仅凭React似乎无法实现。

    我的MasterComponent版本很糟糕,因为我正在用一个新的Img实例替换Img组件,而我只是想更新它拥有的道具。在设置状态上使用forceUpdate也很糟糕,但我对此不太担心。

    我认为,由于MasterComponent不是一个具有可能导致重新渲染器的状态的react组件,并且Img和Switch不在可以有机地接收该状态的渲染函数中,所以我的想法可能行不通。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Alexander Nied    7 年前

    所以我不知道这是 好的 图案这不是超级反应,但我 认为 它将实现您所追求的目标。我还没有测试过,但我想是这样的:

    function getImgSwitchPair() {
    
      const state = {
        isShowing: true
      };
    
      const toggleImg = () => {
        state.isShowing = !state.isShowing;
      };
    
      const Img = () => {
        return (
          <div><img style={{ display: state.isShowing ? 'inline' : 'none', width: '100px' }} src="http://blog.nationalgeographic.org/wp-content/uploads/2010/04/Greatest-Nature-Photographs-of-All-Time-3.jpg" /></div>
        );
      };
    
      const Switch = () => {
        return (
          <div style={{ width: '50px', height: '50px', background: 'black', color: 'white'}} onClick={toggleImg}>
          click me
          </div>
        );
      };
    
      return {
        Img,
        Switch,
        toggleImg
      };
    
    }
    
    
    class Example extends React.Component {
      constructor(props) {
            super(props);
            const {Img, Switch} = getImgSwitchPair();
            this.Img = Img;
            this.Switch = Switch;
      }
    
      render() {
        return ( 
          <div>
            <Img/>
            <Switch/>
          </div>
        );
      }
    }
    

    getImgSwitchPair 生成并返回耦合的 Img Switch 组件以及 toggleImg 如果要手动调用,请使用函数。我们使用 state 对象进行变异以进行更改 isShowing 状态

    认为 这会有用的。然而,它将在React生命周期之外完全存在并更新状态,我认为这是有问题的。所以,虽然这可能有效,但我不确定这是一个好模式。

    我很犹豫是否发布此无测试,因为我知道这可能是一个有问题的模式,但我希望它可能会帮助您找到您想要的。。。

        2
  •  0
  •   alex    7 年前

    因此,我认为这非常好,但要让它更“React tm”,如:

    const Img = (props) => {
    
      return (
        <div>
          <img
            style={{ display: props.isShowing ? 'inline' : 'none', width: '100px' }}
            src="http://blog.nationalgeographic.org/wp-content/uploads/2010/04/Greatest-Nature-Photographs-of-All-Time-3.jpg"/>
        </div>
      );
    };
    
    const Switch = (props) => {
    
      return (
        <div
          style={{ width: '50px', height: '50px', background: 'black', color: 'white'}}
          onClick={props.toggleImg}>
        click me
        </div>
      );
    };
    
    class MasterComponent extends React.Component {
      constructor(props) {
        super(props);
    
        this.state = {
          showImg: true,
        };
    
        this.toggleImg = this.toggleImg.bind(this);
      }
    
      toggleImg() {
        this.setState({showImg: !this.state.showImg});
      }
    
      render() {
        return <div>
          <Img isShowing={this.state.showImg} />
          <Switch toggleImg={this.toggleImg} />
        </div>;
      }
    }
    
    
    class Example extends React.Component {
      render() {
        return <div>
          <MasterComponent />
        </div>;
      }
    }
    
    
    ReactDOM.render(
      <Example />,
      document.getElementById('container')
    );
    

    这样更具可组合性,并且使用react Components类

    此外,您可能对以下内容感兴趣:

    {this.state.showImg && <Img isShowing={true} />}