反应上下文“更新”无法正常工作

时间:2020-05-31 09:32:22

标签: javascript reactjs state

我正在制作自定义标签组件,关闭标签时出现问题。切换选项卡可以正常工作,但是当我关闭最后一个选项卡时,我想设置活动的上一个选项卡,但它不起作用。

setTabs(上下文更新)正在更新对象中的数组“ data”,而不是“ activeTab”。

我正在使用react Context存储选项卡列表和活动选项卡。 切换标签页工作正常,打开新标签页也可以。

TabsContext

import tkinter

_width = 50
_height = 50
_size = 8

root = tkinter.Tk()
root.title("draw me a lovely matrix")
canv = tkinter.Canvas(root, width=_width * _size, height=_height * _size)
rects = []

# This javascript-like approach doesn't work in tkinter because
# <Enter> and <Leave> events aren't called while any mouse buttons
# are held.
def fill(tag):
  canv.itemconfig(tag, fill="#aaa")
def enter(event):
  fill("current")
def mousedown(event):
  fill("current")
  canv.tag_bind("all", "<Enter>", enter, add="+")
def mouseup(event):
  canv.tag_unbind("all", "<Enter>")
canv.bind("<Button-1>", mousedown)
canv.bind("<ButtonRelease-1>", mouseup)

for i in range(_size):
  for j in range(_size):
    rects.append(canv.create_rectangle(_width * j, _height * i, _width * (j + 1), _height * (i + 1), fill="#fff", width=0))

canv.pack()
root.mainloop()

MainTabs组件:

import React, { useReducer, useEffect } from "react";

const initialState = {
  data: [
    {
      name: "Start",
      component: "StartTab",
      cantClose: true,
      params: null
    }
  ],
  activeTab: 0
};

const localState = JSON.parse(localStorage.getItem("tabs"));
const TabsContext = React.createContext();

let reducer = (tabs, newTabs) => {
  if (newTabs === null) {
    localStorage.removeItem("tabs");
    return initialState;
  }
  return { ...tabs, ...newTabs };
};

function TabsProvider(props) {
  const [tabs, setTabs] = useReducer(reducer, localState || initialState);

  useEffect(() => {
    localStorage.setItem("tabs", JSON.stringify(tabs));
  }, [tabs]);

  return (
    <TabsContext.Provider value={{ tabs, setTabs }}>
      {props.children}
    </TabsContext.Provider>
  );
}

export { TabsContext, TabsProvider };

导航组件

import React, { Component, useContext } from "react";
import { TabsContext } from "../../providers/TabsProvider";
import StartTab from "./tab.start";
...

class TabComponent extends Component {
    components = {
        StartTab: StartTab,
        ...
    };

    render() {
        const TagName = this.components[this.props.tag];
        return <TagName />
    }
}

const TabsMain = () => {
    const { tabs, setTabs } = useContext(TabsContext);

    const closeTab = (index) => {
        tabs.data.splice(index, 1);

        if (tabs.activeTab == tabs.data.length ) {
            tabs.activeTab--;
        }

        setTabs({ data: tabs.data, activeTab: tabs.activeTab });
    };

    const tabsNavigation = tabs.data.map((tab, index) =>
        <li key={index}>
            <button
                onClick={() => {
                    setTabs({ data: tabs.data, activeTab: index });
                }}
                className={`${tabs.activeTab == index ? 'active' : ''}`}
            >
                {tab.name}
                <div onClick={() => {
                    closeTab(index);
                }} className={`close_button ${!tab.cantClose ? 'show' : 'hide'}`}>X</div>
            </button>
        </li>
    );

    const tabsPanels = tabs.data.map((tab, index) =>
        <div key={index} className={`panel ${tabs.activeTab == index ? 'active' : ''}`}>
            <TabComponent tag={tab.component} />
        </div>
    );

    return (
        <div className="tabs">
            <ul className="tabs__navigation">
                {tabsNavigation}
            </ul>
            <div className="tabs__content">
                {tabsPanels}
            </div>
        </div>
    );
};

export default TabsMain;

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。 首先,我有双击操作: 1)在标签上点击-selectTab, 2)在同一按钮上的“ X”上,当我单击X时,将触发selectTab和closeTab(setTabs也被触发了两次)

解决方案是从按钮中提取“ X”:

            <button
                onClick={() => {
                    setTabs({ data: tabs.data, activeTab: index });
                }}
                className={`${tabs.activeTab == index ? 'active' : ''}`}
            >
                {tab.name}
            <div onClick={() => {
                closeTab(index);
            }} className={`close_button ${!tab.cantClose ? 'show' : 'hide'}`}>X</div>
            </button>

对此:

            <button
                onClick={() => {
                    setTabs({ data: tabs.data, activeTab: index });
                }}
                className={`${tabs.activeTab == index ? 'active' : ''}`}
            >
                {tab.name}
            </button>
            <div onClick={() => {
                closeTab(index);
            }} className={`close_button ${!tab.cantClose ? 'show' : 'hide'}`}>X</div>

并将closeTab函数更改为此:

    const closeTab = (index) => {
        tabs.data.splice(index, 1);
        setTabs({ data: tabs.data, activeTab: index-1 });
    };