2017-07-12 37 views
1

中的子组件我想创建一个可重用组件,其中每次渲染组件时DOM结构都可能会有所不同。比方说,我有这个React.js渲染组件

class Comp extends React.Component { 
    constructor() { 
     super() 
     this.state = { 
      click: null, 
     } 
    } 
    render() { 
     return(
      <div> 
       {this.props.chidren} 
      </div> 
     ) 
    } 
    handleButton1() { 
     this.setState({click: 'button1'}); 
    } 
    handleButton2() { 
     this.setState({click: 'button2'}); 
    } 
} 
class SubComp1 extends React.Component { 
    render() { 
     return(
      <button onClick={() => this.props.handleButton1()}>Button 1</button> 
     ) 
    } 
} 
class SubComp2 extends React.Component { 
    render() { 
     return (
      <button onClick={() => this.props.handleButton2()}>Button 2</button> 
     ) 
    } 
} 
ReactDOM.render((
<Comp> 
    <div id="somediv"> 
     <div id="andanother"> 
      <SubComp1 /> 
     </div> 
    </div> 
    <div id="andanotherother"> 
     <SubComp2 /> 
    </div> 
</Comp>), document.getElementById('app')) 

目前,两个子做访问各自的处理函数。将handleButton1handleButton2函数传递给子组件的最好方法是假设它们在DOM中的位置是动态的,并且可能会根据页面的布局而改变。 我想到了2个解决方案迄今:

  1. 迭代props.children里面,直到我找到感兴趣的元素,然后与物业

  2. 克隆它使用ref并以某种方式使子组件的主要成分后已通过componentDidMount回调呈现。

你对此有何看法?

+1

你能突出你的问题吗? – divine

回答

1

这是一个地方,使用React的Context将是最直接的解决方案。

另一个解决方案是使用Redux操作,但这会使您的组件更少重复使用,并且与应用程序更紧密地耦合,您可能会也可能不会关心。

+0

(链接中的第一个示例React Context文档应该足够告诉你如何去实现它) – lleaff

+0

谢谢!这看起来像一个工作解决方案。我会尝试并回复你。 –

+0

它工作完美!我还想出了另一个解决方案,将组件的实例传递给子组件,但它需要一些技巧。这完全按预期工作,谢谢! –

1

为什么不能做这样的事情:

class Comp extends React.Component { 
    constructor() { 
     super() 
     this.state = { 
      click: null, 
     } 
    } 
    render() { 
     return(
      <div> 
       {this.props.chidren} 
      </div> 
     ) 
    } 
    handleButton(button) { 
     this.setState({click: button}); 
    } 
} 

然后在子,你可以这样做

class SubComp1 extends React.Component { 
    render() { 
     return(
      <button onClick={() => this.props.handleButton('button1')}>Button 1</button> 
     ) 
    } 
} 

class SubComp2 extends React.Component { 
    render() { 
     return (
      <button onClick={() => this.props.handleButton('button2')}>Button 2</button> 
     ) 
    } 
} 
+0

通过这样做,子组件是否可以从父项访问'this.props.handleButton'? –

+0

我误解了你的问题,在这种情况下,使用'React.cloneElement'和相应的道具似乎是一个不错的选择。 – enzoborgfrantz

+0

但问题在于,它可能需要在查找所需元素之前进行大量循环,具体取决于嵌套级别。 –

1

这可能会满足您的需求的一种替代选择是建立一个高阶组件,它用一些额外的功能来装饰另一个组件,下面是这可能如何为你工作的一个简单例子,

高阶组件:

const Comp = ComposedComponent => 
    class Comp extends React.Component { 
    constructor(props) { 
     super(props) 
     this.handleButton = this.handleButton.bind(this); 
     this.state = { 
      click: null, 
     } 
    } 

    handleButton(button) { 
     this.setState({click: button}); 
    } 

    render() { 
     return(
      <ComposedComponent 
       onClick={this.handleButton} 
      /> 
     ) 
    } 
    } 

    export default Comp; 

的子组件:

class SubComp1 extends React.Component { 
    render() { 
     return(
      <button onClick={() => this.props.onClick('button1')}>Button 1</button> 
     ) 
    } 
} 

如何使用它:

const ExtendedComp = Comp(SubComp1); 

<ExtendedComp /> 

这会是适合你的任务是什么?

+0

如果我要做'const ExtendedComp1 = Comp(SubComp1);'和'const ExtendedComp2 = Comp(SubComp2);',它们会修改相同的'state.click'吗? –

+0

否,因为它们是单独的实例,高阶组件只是简单地将组件作为参数并扩展其功能。一般来说,响应中的状态应与ui相关,如果您打算让许多不同的组件在整个应用程序中访问全局状态,则可以考虑使用状态管理库,例如redux或mobX – enzoborgfrantz