Javascript 在状态中反应上下文和可为空的值

Javascript 在状态中反应上下文和可为空的值,javascript,reactjs,typescript,react-context,Javascript,Reactjs,Typescript,React Context,我试图在react中创建一个上下文,该上下文将保存一些由接口定义的值(Client,在下面的示例中)。我的问题是,它要求我在state接口(ClientState)中使该字段为空,这意味着我必须在使用上下文的任何地方检查空值。我想避免这种情况 示例代码: 接口客户端{ 值1:字符串, 价值2:数字 } 接口客户端状态{ 客户?:客户 } 常量initialState:ClientState={ 客户机:未定义 } const ClientContext=React.createContext(i

我试图在react中创建一个上下文,该上下文将保存一些由接口定义的值(
Client
,在下面的示例中)。我的问题是,它要求我在state接口(
ClientState
)中使该字段为空,这意味着我必须在使用上下文的任何地方检查空值。我想避免这种情况

示例代码:

接口客户端{
值1:字符串,
价值2:数字
}
接口客户端状态{
客户?:客户
}
常量initialState:ClientState={
客户机:未定义
}
const ClientContext=React.createContext(initialState);
export const useClient=():ClientState=>useContext(ClientContext);
export const EmployeeContextProvider=({children}:PropsWithChildren)=>{
const[state,setState]=useState({});
//抽象的,与这个问题无关
常量加载文件=()=>{
设定状态(
{
值1:“测试”,
价值2:1
}
)
}
useffect(()=>loadFiles(),[]);
返回(
{儿童}
)
}
到目前为止,我已经尝试过并认为不令人满意:

  • initialState
    中的
    client
    字段提供一个虚拟对象。问题是这个的真实版本有大量的字段,这意味着大量的伪代码
  • Client
    接口的成员向
    useClient()
    添加检查,问题与1相同

  • 另一个半相关性是,我不需要在初始化之后修改此上下文,并且它完全可以是只读的。

    client
    需要是可选的,因为它的值是从初始化为空对象的
    状态设置的。
    state
    的类型被推断为
    ClientState

    useState({})
    要求
    ClientState
    的所有属性都是可选的

    您可以使用
    useState({}as ClientState)
    强制TypeScript接受一个空(伪)对象,就好像它符合ClientState一样,但这意味着您的提供程序实际上将提供一个不可用的客户端,直到用真实的客户端调用了
    setState

    但这似乎是您希望解决的问题,每次您希望使用客户端时,都要检查null/undefined


    TypeScript也许在这里拯救了你自己。如果你的客户真的无法定义,那么你应该在每次使用它时检查它

    客户端
    需要是可选的,因为它的值是从初始化为空对象的
    状态
    设置的。
    state
    的类型被推断为
    ClientState

    useState({})
    要求
    ClientState
    的所有属性都是可选的

    您可以使用
    useState({}as ClientState)
    强制TypeScript接受一个空(伪)对象,就好像它符合ClientState一样,但这意味着您的提供程序实际上将提供一个不可用的客户端,直到用真实的客户端调用了
    setState

    但这似乎是您希望解决的问题,每次您希望使用客户端时,都要检查null/undefined


    TypeScript也许在这里拯救了你自己。如果你的客户真的无法定义,那么你应该在每次使用它时检查它

    我想这正是你想要的

    您的ClientState类型似乎只允许客户机未定义,您说过您不希望这样,所以我假设您不希望这样。此外,它与设置客户端而不是客户端状态的setState调用相冲突

    这允许空客户机处于状态,但不在上下文中。防护确保在设置客户端之前不会呈现上下文及其子级

    import React, { PropsWithChildren, useContext, useEffect, useState } from "react";
    
    interface Client {
        value1: string,
        value2: number
    }
    
    // Note: ClientContext is initialised with an unusable Client object
    const ClientContext = React.createContext<Client>({} as Client);
    
    export const useClient = (): Client => useContext(ClientContext);
    
    export const EmployeeContextProvider = ({ children }: PropsWithChildren<{}>) => {
        // We allow state to be set to null
        const [state, setState] = useState<Client | null>(null);
    
        // abstracted, not relevant to this problem
        const loadFiles = () => {
            setState(
                {
                    value1: "test",
                    value2: 1
                }
            )
        }
    
        useEffect(() => loadFiles(), []);
    
        // Guard against null so that state can be provided as a Client
        return (
            state != null ?
                <ClientContext.Provider value={state} >
                    {children}
                </ClientContext.Provider>
                : null
        )
    }
    
    import React,{PropsWithChildren,useContext,useffect,useState}来自“React”;
    接口客户端{
    值1:字符串,
    价值2:数字
    }
    //注意:ClientContext是用一个不可用的客户端对象初始化的
    const ClientContext=React.createContext({}作为客户端);
    export const useClient=():Client=>useContext(ClientContext);
    export const EmployeeContextProvider=({children}:PropsWithChildren)=>{
    //我们允许将状态设置为null
    const[state,setState]=useState(null);
    //抽象的,与这个问题无关
    常量加载文件=()=>{
    设定状态(
    {
    值1:“测试”,
    价值2:1
    }
    )
    }
    useffect(()=>loadFiles(),[]);
    //防止null,以便可以将状态作为客户端提供
    返回(
    状态!=null?
    {儿童}
    :null
    )
    }
    
    我想这正是你想要的

    您的ClientState类型似乎只允许客户机未定义,您说过您不希望这样,所以我假设您不希望这样。此外,它与设置客户端而不是客户端状态的setState调用相冲突

    这允许空客户机处于状态,但不在上下文中。防护确保在设置客户端之前不会呈现上下文及其子级

    import React, { PropsWithChildren, useContext, useEffect, useState } from "react";
    
    interface Client {
        value1: string,
        value2: number
    }
    
    // Note: ClientContext is initialised with an unusable Client object
    const ClientContext = React.createContext<Client>({} as Client);
    
    export const useClient = (): Client => useContext(ClientContext);
    
    export const EmployeeContextProvider = ({ children }: PropsWithChildren<{}>) => {
        // We allow state to be set to null
        const [state, setState] = useState<Client | null>(null);
    
        // abstracted, not relevant to this problem
        const loadFiles = () => {
            setState(
                {
                    value1: "test",
                    value2: 1
                }
            )
        }
    
        useEffect(() => loadFiles(), []);
    
        // Guard against null so that state can be provided as a Client
        return (
            state != null ?
                <ClientContext.Provider value={state} >
                    {children}
                </ClientContext.Provider>
                : null
        )
    }
    
    import React,{PropsWithChildren,useContext,useffect,useState}来自“React”;
    接口客户端{
    值1:字符串,
    价值2:数字
    }
    //注意:ClientContext是用一个不可用的客户端对象初始化的
    const ClientContext=React.createContext({}作为客户端);
    export const useClient=():Client=>useContext(ClientContext);
    export const EmployeeContextProvider=({children}:PropsWithChildren)=>{
    //我们允许将状态设置为null
    const[state,setState]=useState(null);
    //抽象的,与这个问题无关
    常量加载文件=()=>{
    设定状态(
    {