【问题标题】:How to fix error "cannot invoke an object which is possibly undefined" using react and typescript?如何使用反应和打字稿修复错误“无法调用可能未定义的对象”?
【发布时间】:2020-05-25 07:33:13
【问题描述】:

我想使用 react 和 typescript 修复错误“无法调用可能未定义的对象”。

我想做什么? 我正在使用 usecontext react hook 并在组件(home、Dialog 和 books 组件)中从它创建一个变量(dialogContext)。这样做我得到了上面提到的错误。

我在帮助文件中定义 DialogContext,如下所示

interface ContextProps {
    setDialogOpen?: (open: boolean) => void;   
}

export const DialogContext = React.createContext<ContextProps>({});

并在需要的组件(Main、home、Dialog 组件)中导入 DialogContext

function MainComponent() {
  let [showDialog, setShowDialog] = React.useState(false);
  return (
      <DialogContext.Provider
          value={{
              setDialogOpen: (open: boolean) => {
                  if (open) {
                      const sessionDialogClosed = sessionStorage.getItem('dialog');
                      if (sessionDialogClosed !== 'closed') {
                          setShowDialog(open);
                          sessionStorage.setItem('dialog', 'closed');
                      }
                  } else {
                      setShowDialog(open);
                  }
              },
          }}
      >
      {showDialog && <Dialog DialogContext={DialogContext}/>
          <Route 
              path="/items">
              <Home />
          </Route>
          <Route
              path="/id/item_id">
              <Books/>
          </Route>
      </DialogContext.Provider>
  )     
}


function Home() {
    const dialogContext= React.useContext(DialogContext);
    const handleClick = () {
        dialogContext.setDialogOpen(true); //get error here
    }
    return ( 
        <button onClick={handleClick}>add</button>
    )
}


function Books({DialogContext} : Props) {
    const dialogContext= React.useContext(DialogContext);
    const handleClick = () {
        dialogContext.setDialogOpen(true); //get error here
    }
    return ( 
        <button onClick={handleClick()}>Click me</button>
    )    
}

function Dialog() {
    return(
        <div>
            //sometext
           <button onClick={dialogContext.setDialogOpen(false)}> hide</button> //get errror here
        </div>
   ) 

}

我尝试了什么?

我添加了一个未定义的检查,其中 dialogContext 在组件(书籍、主页、对话框)中使用,例如我在下面使用的书籍组件中,

function Books({DialogContext} : Props) {
    const dialogContext= React.useContext(DialogContext);
    const handleClick = () {
        if (dialogContext !== 'undefined') {
            dialogContext.setDialogOpen(true); //get error here
        }
    }
    return ( 
        <button onClick={handleClick()}>Click me</button>
    )    
}

但仍然抛出错误“无法调用可能未定义的对象”。

谁能帮我解决这个错误。谢谢。

编辑:

我尝试在下面做,它消除了错误

function Books({DialogContext} : Props) {
    const dialogContext= React.useContext(DialogContext);
    const handleClick = () {
        if (dialogContext && dialogContext.setDialogOpen) {
            dialogContext.setDialogOpen(true); 
        }
    }
    return ( 
        <button onClick={handleClick()}>Click me</button>
    )    
}

但是,与其在每个组件中添加这样的检查,我应该在 DialogContext 帮助程序文件中进行哪些更改,或者需要更改哪些内容来修复继续检查未定义或未定义。谢谢。

【问题讨论】:

  • dialogContext?.setDialogOpen 不行吗?
  • 使用 dialogContext 的意思? dialogContext.setDialogOpen : null; ???嗯,它不工作。
  • 我已经按照 DialogContext 的定义方式更新了我的问题。

标签: reactjs typescript


【解决方案1】:

您的代码中有很多输入错误,我已根据您的 cmets 编辑了答案,这是最终结果。您还可以在代码和框中查看它是如何工作的,只需 click here 即可查看。

这是你所有的代码 + 一些修复 + 结构上的一点改变


interface ContextProps {
  setDialogOpen: (open: boolean) => void;
}

const DialogContext = React.createContext<ContextProps>({
  setDialogOpen: (open: boolean) => {}
});

function Home() {
  const dialogContext = React.useContext(DialogContext);
  const handleClick = () => {
    dialogContext.setDialogOpen(true); //It's Ok
  };

  return <button onClick={handleClick}>add</button>;
}

function Books() {
  const dialogContext = React.useContext(DialogContext);
  const handleClick = () => {
    dialogContext.setDialogOpen(true); //get error here
  };
  return <button onClick={handleClick}>Click me</button>;
}

function Dialog() {
  const dialogContext = React.useContext(DialogContext);
  const handleClick = () => {
    dialogContext.setDialogOpen(false);
  };
  return (
    <div>
      <button onClick={handleClick}> hide</button>
    </div>
  );
}

export default function MainComponent() {
  const [showDialog, setShowDialog] = React.useState(false);
  console.log("hi");
  const setDialogOpen = (open: boolean) => {
    if (open) {
      // const sessionDialogClosed = sessionStorage.getItem("dialog");
      // if (sessionDialogClosed !== "closed") {
      setShowDialog(open);
      //   sessionStorage.setItem("dialog", "closed");
      // }
    } else {
      setShowDialog(open);
    }
  };
  return (
    <DialogContext.Provider
      value={{
        setDialogOpen
      }}
    >
      {showDialog && <Dialog />}
      <Router>
        <Switch>
          <Route path="/">
            <Home />
          </Route>
          <Route path="/books">
            <Books />
          </Route>
        </Switch>
      </Router>
    </DialogContext.Provider>
  );
}

【讨论】:

  • 删除后? setDialogOpen 的字符意味着将其从可选中删除然后给我一个错误“类型 {} 的参数不可分配给类型为'ContextProps'的参数。类型 {} 中缺少属性 setDialogOpen 但在 ContextProps 中是必需的。
  • 我在这一行得到了这个 export const DialogContext = React.createContext({});而且问题中的这个错误仍然存​​在
  • 似乎我必须在这一行中传递一些默认值 export const DialogContext = React.createContext({});不知道那会是什么
  • 我已经编辑了代码,你可以在代码沙箱上玩一下:codesandbox.io/s/great-dew-7zml2?file=/src/App.tsx:107-1782
【解决方案2】:

为上下文提供默认值是没有意义的。它是多余的样板文件,尤其是在它很复杂的时候。

只是伪造类型:

const DialogContext = createContext(null as any as ContextProps);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-06
    • 2019-12-24
    • 2022-11-10
    • 1970-01-01
    • 2020-02-21
    • 2021-11-27
    • 2021-12-17
    • 2019-07-30
    相关资源
    最近更新 更多