繁体   English   中英

如何使用 react 和 typescript 在 function 中调用 useContext?

[英]How to call useContext in a function using react and typescript?

我已经为设置状态定义了如下上下文,如下所示,

interface DialogsCtxState {
    isDialogOpen: boolean;
    setIsDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
    itemVisible: boolean;
    setItemVisible: React.Dispatch<React.SetStateAction<boolean>>;
}

const initialState: DialogsCtxState = {
    isDialogOpen: false,
    setIsDialogOpen: () => {},
    itemVisible: false,
    setItemVisible: () => {},
};

export const DialogsContext = React.createContext<
    DialogsCtxState
>(initialState);

export const DialogsContextProvider: React.FC = ({ children }) => {
    const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>(
        false
    );
    const [itemsVisible, setItemsVisible] = React.useState<boolean>(
        false
    );

    return (
        <DialogsContext.Provider
            value={{
                isDialogOpen,
                setIsDialogOpen,
                itemVisible,
                setItemVisible,
            }}
        >
            {children}
        </DialogsContext.Provider>
    );
};

我在两个组件 Uploadbutton 和 userbutton 中使用这个上下文,如下所示,

function UploadButton() {
    const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} = 
    React.useContext(DialogContext);
    const onUpload = () => {
        itemVisible && setItemVisible(false);
        setIsDialogOpen(isDialogOpen => !isDialogOpen);
    }
    return (
        <Button onClick={onUpload}/>
    );
}

function UserButton() {
    const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} = 
    React.useContext(DialogContext);
    const onAdd = () => {
        isDialogOpen && setIsDialogOpen(false);
        setItemVisible(prev => !prev);
    }
    return (
        <Button onClick={onAdd}/>
    );
}

上面的代码片段工作正常。 但我想将带有 onUpload 和 onAdd 方法的代码移动到 DialogContext 文件,该文件的计算结果如下所示,

const onAdd = () => {
    function1(); //where thiscontains the code in onAdd before snippet.
}

const onUpload = () => {
    function2();//where this contains code in onUpload snippet before
}

我尝试过的,

在包含 DialogContext 的文件中,我尝试了类似下面的内容,

export const function1 = () => {
    const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} = 
    React.useContext(DialogContext); //error here
    isDialogOpen && setIsDialogOpen(false);
    setItemVisible(prev => !prev);
}

export const function2 = () => {
    const {isDialogOpen, setIsDialogOpen, itemVisible, setItemVisible} = 
    React.useContext(DialogContext); //error here
    itemVisible && setItemVisible(false);
    setIsDialogOpen(isDialogOpen => !isDialogOpen);
}

但是我得到错误 react.usecontext is used in a function 这既不是反应 function 组件也不是自定义反应钩子。

我怎样才能解决这个问题。 有人可以帮我解决这个问题。 谢谢。

看起来从上下文返回的值的唯一用途是创建onUploadonAdd函数。 DialogsContextProvider组件中创建函数以将它们作为值传递将是一种更好的方法。 例子

// context
interface DialogsCtxState {
   onUpload: () => void;
   onAdd: () => void;
};

const initialState: DialogsCtxState = {
   onUpload: () => {},
   onAdd: () => {}
};

export const DialogsContext = React.createContext<
    DialogsCtxState
>(initialState);

DialogsContextProvider组件

// context provider
export const DialogsContextProvider: React.FC = ({ children }) => {
    const [isDialogOpen, setIsDialogOpen] = React.useState<boolean>(
        false
    );

    const [itemsVisible, setItemsVisible] = React.useState<boolean>(
        false
    );

    // onUpload function
    const onUpload = useCallback(() => {
        itemsVisible && setItemsVisible(false);
        setIsDialogOpen((isDialogOpen) => !isDialogOpen);
    }, [itemsVisible]);

    // onAdd function
    const onAdd = useCallback(() => {
        isDialogOpen && setIsDialogOpen(false);
        setItemsVisible((prev) => !prev);
    }, [isDialogOpen]);

    return (
        <DialogsContext.Provider value={{ onAdd, onUpload}}>
            {children}
        </DialogsContext.Provider>
    );
};

这就是它在UploadButtonUserButton组件中的使用方式,

const UserButton: React.FC = () => {
   const { onAdd } = React.useContext(DialogsContext)
  
   // rest of the logic
}

const UploadButton: React.FC = () => {
   const { onUpload } = React.useContext(DialogsContext)
  
   // rest of the logic
}

注意您的代码中有多个拼写错误,因此如果我们忽略了在您采用自定义 function 方法时发生的错误,因为useContext只能用于功能组件自定义钩子 要解决这个问题,您必须采用自定义挂钩方法。 例如

export const useOnUpload = () => {
  const { isDialogOpen, setIsDialogOpen, itemsVisible, setItemsVisible,
  } = React.useContext(DialogsContext);

  const onUpload = useCallback(() => {
    itemsVisible && setItemsVisible(false);
    setIsDialogOpen((isDialogOpen) => !isDialogOpen);
  }, [itemsVisible, setIsDialogOpen, setItemsVisible]);

  return onUpload;
};

// usage
function UploadButton() {
   const onUpload = useOnUpload();

   // rest of the logic
}

// similarly you can create the onUseAdd hook

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM