如何使我的自定义选项卡组件能够将索引传递给子项并隐藏窗格?
How to make my custom tab component work with passing index to children and hiding panes?
我正在尝试创建一个自定义选项卡组件,以便我可以学习更多反应,但是我被卡住了。
共有三个组件,灵感来自 Material-UI 选项卡。选项卡、选项卡和 TabPane。
Tabs.js
const Tabs = (props) => {
const { children, defaultTab } = props;
const [activeTab, setActiveTab] = useState(defaultTab);
const onTabClick = (clickedTab = 0) => {
setActiveTab(clickedTab);
}
return (
<div className="tabs">
{children}
</div>
)
}
这应该保持 activeTab 状态并且能够告诉 Tab 和 TabPane 活动选项卡(或者应该吗?)。
Tab.js
const Tab = (props) => {
const { label } = props;
return (
<li className="tabs-tab" onClick={ }> {label} </li>
)
}
export default Tab;
Tab 组件有 onClick
和一个标签。但是,我不确定如何通过子组件将函数 onTabClick
从 Tabs
传递给此组件。
TabPane.js
const TabPane = (props) => {
const { children } = props;
return (
<div className="tabs-tab-pane">
{children}
</div>
)
}
export default TabPane;
这是每个选项卡内容的容器。我不确定如何从此处获取选项卡中的数据,因此我知道何时隐藏窗格。
代码分享如下:
这里是 url 查看此代码和预览:https://codesandbox.io/s/objective-mendel-752qe?fontsize=14
如何使用此功能?
您可以使用这种依赖于 React Context 的方法。根据您的需要,将所有状态放在顶层 App
并通过 props 传递数据 可能 更简单,但这种方法可以根据您的需要提供更多的可扩展性.
const TabContext = React.createContext();
const Tabs = props => {
const { children, defaultTab } = props;
const [activeTab, setActiveTab] = React.useState(defaultTab);
return (
<TabContext.Provider value={{ activeTab, setActiveTab }}>
{children}
</TabContext.Provider>
);
};
const Tab = props => {
const { activeTab, setActiveTab } = React.useContext(TabContext);
const { label, tabIndex } = props;
const active = activeTab === tabIndex;
return (
<li
onClick={() => setActiveTab(tabIndex)}
className={`tabs-tab ${active ? "active" : ""}`}
>
{" "}
{label}{" "}
</li>
);
};
const TabPane = props => {
const { activeTab } = React.useContext(TabContext);
const { children, tabIndex } = props;
if (activeTab === tabIndex) {
return <div className="tabs-tab-pane">{children}</div>;
} else {
return null;
}
};
function App() {
return (
<div className="App">
<Tabs defaultTab={0}>
<div className="tabs">
<Tab label="Home" tabIndex={0} />
<Tab label="Contact" tabIndex={1} />
</div>
<TabPane tabIndex={0}>Tab Content for Home</TabPane>
<TabPane tabIndex={1}>Tab Content for Contact</TabPane>
</Tabs>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
font-family: sans-serif;
text-align: center;
width: 500px;
margin: 0 auto;
}
.tabs {
display: flex;
list-style-type: none;
background: #eee;
padding: 3px 0;
}
.tabs .tabs-tab {
padding: 5px 10px;
color: #000;
cursor: pointer;
}
.tabs .tabs-tab.active {
background: orange;
}
.tabs .tabs-tab:hover {
background: #777;
color: #fff;
}
.tabs-tab-pane {
padding: 10px;
padding: 10px;
margin: 10px;
background: #eee;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
我正在尝试创建一个自定义选项卡组件,以便我可以学习更多反应,但是我被卡住了。
共有三个组件,灵感来自 Material-UI 选项卡。选项卡、选项卡和 TabPane。
Tabs.js
const Tabs = (props) => {
const { children, defaultTab } = props;
const [activeTab, setActiveTab] = useState(defaultTab);
const onTabClick = (clickedTab = 0) => {
setActiveTab(clickedTab);
}
return (
<div className="tabs">
{children}
</div>
)
}
这应该保持 activeTab 状态并且能够告诉 Tab 和 TabPane 活动选项卡(或者应该吗?)。
Tab.js
const Tab = (props) => {
const { label } = props;
return (
<li className="tabs-tab" onClick={ }> {label} </li>
)
}
export default Tab;
Tab 组件有 onClick
和一个标签。但是,我不确定如何通过子组件将函数 onTabClick
从 Tabs
传递给此组件。
TabPane.js
const TabPane = (props) => {
const { children } = props;
return (
<div className="tabs-tab-pane">
{children}
</div>
)
}
export default TabPane;
这是每个选项卡内容的容器。我不确定如何从此处获取选项卡中的数据,因此我知道何时隐藏窗格。
代码分享如下:
这里是 url 查看此代码和预览:https://codesandbox.io/s/objective-mendel-752qe?fontsize=14
如何使用此功能?
您可以使用这种依赖于 React Context 的方法。根据您的需要,将所有状态放在顶层 App
并通过 props 传递数据 可能 更简单,但这种方法可以根据您的需要提供更多的可扩展性.
const TabContext = React.createContext();
const Tabs = props => {
const { children, defaultTab } = props;
const [activeTab, setActiveTab] = React.useState(defaultTab);
return (
<TabContext.Provider value={{ activeTab, setActiveTab }}>
{children}
</TabContext.Provider>
);
};
const Tab = props => {
const { activeTab, setActiveTab } = React.useContext(TabContext);
const { label, tabIndex } = props;
const active = activeTab === tabIndex;
return (
<li
onClick={() => setActiveTab(tabIndex)}
className={`tabs-tab ${active ? "active" : ""}`}
>
{" "}
{label}{" "}
</li>
);
};
const TabPane = props => {
const { activeTab } = React.useContext(TabContext);
const { children, tabIndex } = props;
if (activeTab === tabIndex) {
return <div className="tabs-tab-pane">{children}</div>;
} else {
return null;
}
};
function App() {
return (
<div className="App">
<Tabs defaultTab={0}>
<div className="tabs">
<Tab label="Home" tabIndex={0} />
<Tab label="Contact" tabIndex={1} />
</div>
<TabPane tabIndex={0}>Tab Content for Home</TabPane>
<TabPane tabIndex={1}>Tab Content for Contact</TabPane>
</Tabs>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
font-family: sans-serif;
text-align: center;
width: 500px;
margin: 0 auto;
}
.tabs {
display: flex;
list-style-type: none;
background: #eee;
padding: 3px 0;
}
.tabs .tabs-tab {
padding: 5px 10px;
color: #000;
cursor: pointer;
}
.tabs .tabs-tab.active {
background: orange;
}
.tabs .tabs-tab:hover {
background: #777;
color: #fff;
}
.tabs-tab-pane {
padding: 10px;
padding: 10px;
margin: 10px;
background: #eee;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>