试图在反应中创建一个特殊的设计模式,不确定如何实现它

时间:2018-03-20 03:48:25

标签: javascript reactjs design-patterns components

我有两个连接的组件,它们都需要相同的父级,以便它们可以相互通信。但是我希望能够将它们渲染到任何地方,100%分开。我有一个jsfiddle示例来展示这个想法,这是我的问题的一个可怕的解决方案,因为每当我需要更改传入的道具时我都会创建一个新的Img组件。但它显示了这个想法。我觉得我可能会犯这个错误,但也许有一种方法可以将道具传递给Img,而不需要制作新的实例。将非React类作为父级是不可取的。

小提琴说明: 制作一个Img组件,它接受一个道具告诉它是否应该渲染 制作一个Switch组件,用于在单击时更改传递给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'成为某种父类,它为你提供两个在状态/道具领域相互交互的子元素,但是像Example的渲染一样单独渲染。因此,想象一下导入MasterComponent然后像我在Example组件中那样使用它,而不知道幕后发生了什么。这就是我希望的设计模式,但是单独使用React似乎无法实现。

我的MasterComponent版本很糟糕,因为当我真的只想更新它拥有的道具时,我正在使用不同道具的Img新实例替换Img组件。在setState上使用forceUpdate也不好,但我不太关心。

我认为,因为MasterComponent不是具有可以导致重新渲染的状态的反应组件,并且Img和Switch不在渲染函数内部,在那里它们可以有机地接收该状态,也许我的想法不起作用。

2 个答案:

答案 0 :(得分:1)

所以...我不知道这是一个好的模式......它不是超级React-y,但是我认为它会实现你想要的。我还没有对它进行测试,但我想的是这样的事情:

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生成并返回已耦合的ImgSwitch组件,以及toggleImg函数(如果您想手动调用它)。我们使用state对象进行变异以更改isShowing状态。

认为这会起作用。但是,它会存在并完全在React生命周期之外更新状态,我认为这会有问题。所以虽然这可行,但我并不乐观,这是一个好的模式。

我不愿意发布这个不进行测试,并且知道这可能是一个有问题的模式,但我希望它可能会让你走上你正在寻找的道路。

答案 1 :(得分:0)

所以我认为这样做很不错,但要做得更多&#34; React tm&#34;像:

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} />}