使用钩子时替代innerRef

时间:2019-05-03 04:23:10

标签: javascript reactjs react-hooks

我正在转换基于类的组件以响应钩子。我对使用ref部分感到困惑。因为,我使用它的方式使我感到The "innerRef" API has been removed in styled-components v4 in favor of React 16 ref forwarding, use "ref" instead like a typical component.

使用钩子时如何使它工作?

const Tabs = ({activeTab, children}) => {
  const [tabsElements, setTabsElements] = useState([])

  return (
    <TabsContext.TabProvider activeTab={activeTab}>
      <TabsContext.TabConsumer>
        {value => (
          <ReactTabs>
            <TabsContainer>
              <ListTabs>
                {value.context.tabs.map(tab => (
                  <TabTitleItem
                    key={tab.id}
                    onClick={value.context.onClick(tab)}
                    id={tab.id}
                    innerRef={tabElement => {
                      if (!tabsElements[tab.id]) {
                        setTabsElements(tabElements => ({
                          ...tabElements,
                          [tab.id]: tabElement,
                        }))
                      }
                    }}
                    isActiveTab={value.context.activeTab.id === tab.id}
                  >
                    <TabAnchorItem>{tab.title}</TabAnchorItem>
                  </TabTitleItem>
                ))}
              </ListTabs>

              <ActiveTabBorder
                activeTabElement={tabsElements[value.context.activeTab.id]}
              />
            </TabsContainer>

            {children}
          </ReactTabs>
        )}
      </TabsContext.TabConsumer>
    </TabsContext.TabProvider>
  )
}

这是演示

https://codesandbox.io/s/z3moq8662p

1 个答案:

答案 0 :(得分:0)

首先,您无法在ref回调方法中更新状态。其次,您只需要传递ref而不是innerRefTabTitleItem组件,因为它在内部使用forwardRef

处理引用。
const Tabs = ({ activeTab, children }) => {
  const [tabsElements, setTabsElements] = useState([]);
  const tabElements = useRef({});

  return (
    <TabsContext.TabProvider activeTab={activeTab}>
      <TabsContext.TabConsumer>
        {value => (
          <ReactTabs>
            <TabsContainer>
              <ListTabs>
                {console.log("value", value.context)}
                {value.context.tabs.map(tab => (
                  <TabTitleItem
                    key={tab.id}
                    onClick={value.context.onClick(tab)}
                    id={tab.id}
                    ref={tabElement => {
                      tabElements.current[tab.id] = tabElement;
                    }}
                    isActiveTab={value.context.activeTab.id === tab.id}
                  >
                    <TabAnchorItem>{tab.title}</TabAnchorItem>
                  </TabTitleItem>
                ))}
              </ListTabs>
              <ActiveTabBorder
                activeTabElement={tabsElements[value.context.activeTab.id]}
              />
            </TabsContainer>

            {children}
          </ReactTabs>
        )}
      </TabsContext.TabConsumer>
    </TabsContext.TabProvider>
  );
};

Working demo