2017-08-05 52 views
1

我有一个React应用程序,其中包含选项卡和显示的子项。如何将参数传递给React子的绑定函数?

<App> 
    <Nav> 
     <Tab1></Tab1> 
     <Tab2></Tab2> 
     <Tab3></Tab3> 
    </Nav> 
    <Section>Display Stuff Here</Section> 
    <Footer></Footer> 
</App> 

当我创造应用中的标签,我有一个for循环,追加在地图变量的标签(这是应用程序的子阵营组件)。

for(...) { 
    tab = React.createElement(Tab, {changeDisplay:() => {this.handleClick(this.changeDisplay(i)}}); 
    myMap.set(i, tab); 
} 

它应该做的是传递从for循环递增的i变量。我甚至做了一个console.log以确保它通过了1,2,3,4。然而,实际显示的是最后一个变量:4.

在Tab类中,我有权访问调用道具:

class Tab extends React.Component { 
    constructor(props) { 
     super(props); 
     this.tab = React.Component('div', null); 
    } 
    render() { 
     return this.tab; 
    } 
    componentDidMount() { 
     this.forceUpdate(); 
    } 
    componentWillUpdate(nextProps, nextState) { 
     this.tab = React.Component('div', {onClick: nextProps.changeDisplay}); 
    } 
} 

为changeDisplay的值应该是唯一的每个标签,以便TAB2应该只具有2的值,并且TAB3应该只有3等的for循环不应该是使下值添加到已经创建的任何以前的标签,因为它们已经制作并附加到地图变量中。

有关如何使这项工作的任何建议?

我可以自定义函数:

changeDisplay1() { changeDisplay(1) }; 
changeDisplay2() { changeDisplay(2) }; 
changeDisplay3() { changeDisplay{3) }; 
changeDisplay4() { changeDisplay(4) }; 

不过,我想这样做的正确的方式,而不是使得黑客。

+0

相关:https://stackoverflow.com/q/750486/5647260 – Li357

+0

任何你不以另一种方式去做的理由?还是你坚持让它以这种方式工作? – Win

回答

0

React功能非常强大,您可以找到多种基于父状态呈现组件列表的方法。这里有一个我已经拉在一起的快速版本。

你可以在这里查看工作副本:https://codesandbox.io/s/zzqLPrjO

说明:

我们创造可用,active tab,用于存储数据,如标签父组件。我们通过从Library对象上的键创建数组来加载可用的选项卡。 (这是完全可选的,但更容易添加额外的选项卡)

一旦选项卡加载到父组件中,我还创建了一个函数来设置/更改active tab。这将传递到我们的地图中的标签,该标签呈现从Library对象中拾取的每个标签。

在我们的Tab组件中,我们只是呈现名称以及挂钩到我们父组件的点击事件,这会将active tab更改为已被点击的标签。 (注意:请注意,我们如何避免渲染方法中的函数绑定,以便每次渲染组件时都不会创建新函数(这被认为是不好的做法,这就是为什么我会避免这种做法。)

一旦活动标签已经改变,我们做一个基本的查找到Library和渲染连接到该指数的成分

import React from 'react'; 
 
import { render } from 'react-dom'; 
 

 
// *--------------------- 
 
// | Tab Component 
 
// *--------------------- 
 

 
const activeTab = { 
 
    background: 'green', 
 
} 
 

 
class Tab extends React.Component { 
 
    change =() => this.props.change(this.props.name) 
 
    render =() => { 
 
    const { 
 
     name: NAME, 
 
     active: ACTIVE, 
 
    } = this.props; 
 
    const isActive = ACTIVE === NAME ? activeTab : null; 
 
    return <button style={isActive} onClick={this.change}>{this.props.name}</button> 
 
    } 
 
} 
 
    
 
// *--------------------- 
 
// | Mock list of Components 
 
// *--------------------- 
 
    
 
const Home =() => <div>Home</div> 
 
const About =() => <div>About</div> 
 

 
// *--------------------- 
 
// | Library of Components 
 
// *--------------------- 
 

 
const Library = { 
 
    Home, 
 
    About 
 
} 
 

 
// *--------------------- 
 
// | Display Components 
 
// *--------------------- 
 
    
 
const Display = ({screen}) => { 
 
    const Comp = Library[screen]; 
 
    return screen === null ? <div>Please select a tab</div> : <Comp/> 
 
} 
 

 
// *--------------------- 
 
// | Main App 
 
// *--------------------- 
 

 
class App extends React.Component { 
 
    state = { 
 
    tabs: [], 
 
    activeTab: null, 
 
    } 
 
    componentWillMount() { 
 
    const tabs = Object.keys(Library); 
 
    this.setState({ 
 
     tabs: tabs 
 
    }); 
 
    } 
 
    changeTab = (tab) => { 
 
    this.setState({ activeTab: tab }); 
 
    } 
 
    render() { 
 
    return (
 
     <div> 
 
     { this.state.tabs.map((tab,index) => { 
 
      return <Tab key={index} name={tab} active={this.state.activeTab} change={this.changeTab} /> 
 
     }) } 
 
     <Display screen={this.state.activeTab} /> 
 
     </div> 
 
    ) 
 
    } 
 
} 
 

 
render(<App />, document.getElementById('root'));

+0

我想给安德鲁李最好的回答for循环修复,但这绝对引导我在概念上正确的方向(即这是一个艰难的决定)。我确实有更新Tabs的问题。我有一个CSS类,显示一个标签为点击/活动。因此,我可以显示标签2被点击并且现在处于活动状态,但它不会强制标签1更新并将其自身与新的活动标签(2)进行比较以重置为非活动状态。 – DeadSupra

+0

@DeadSupra该示例已更新为活动标签样式。如果您将其从父状态挂钩,那么当您更改活动选项卡时,它将重新呈现子组件。让我知道你是否需要更多信息。 :) – Win

+0

完美。对我自己的代码做了轻微的修改,但总体上让我走上了正确的道路。非常感谢 – DeadSupra