如何使我的自定义选项卡组件能够将索引传递给子项并隐藏窗格?

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 和一个标签。但是,我不确定如何通过子组件将函数 onTabClickTabs 传递给此组件。

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>