【问题标题】:React Context and Provider - TypeError: variable is undefined反应上下文和提供者 - 类型错误:变量未定义
【发布时间】:2021-12-04 16:15:54
【问题描述】:

我试图有一个按钮,以便在按下时修改 React 上下文。 也就是说,我的上下文仅包含一个字符串列表,当 GET 请求成功时会填充该列表。 响应示例如下:

{
  "message": "OK",
  "status-code": 200,
  "data": {
    "models": [
      "model1",
      "model2",
      "model3"
    ]
  }
}

关于更新我的上下文的代码如下:

import React from 'react'
import {
    VStack,
    Button,
    OrderedList,
    ListItem
} from '@chakra-ui/react'

const Endpoint = 'http://localhost:5000/'

const ModelsContext = React.createContext([])

function Models() {
    const [models, setModels] = React.useContext(ModelsContext)
    const updateModels = async () => {
        await fetch(Endpoint + 'models', {
            method: 'GET',
            headers: {
                Accept: 'application/json'
            }
        })
        .then((resp) => resp.json())
        .then(function(data) {
            setModels(data.models)
        })
    }

    return (
        <VStack>
            <Button
                size="sm"
                colorScheme='teal'
                variant='solid'
                onClick={updateModels}>
            Get Models List
            </Button>
            <ModelsContext.Provider value={{models}}>
                <OrderedList>
                {
                    models.map((name) => (
                        <ListItem>
                            {name}
                        </ListItem>
                    ))
                }
                </OrderedList>
            </ModelsContext.Provider>
        </VStack>
    )
}

export default Models

我还需要将结果显示为 Chakra-UI 有序列表。但是,models 变量在 &lt;OrderedList /&gt; 块内仍未定义,即使我定义了 React Provider Context 块。 我得到的实际错误是:&lt;OrderedList&gt; 位置的“TypeError:模型未定义”。

提前谢谢你!

【问题讨论】:

    标签: javascript reactjs chakra-ui


    【解决方案1】:

    您没有正确使用上下文。上下文用于在没有道具钻孔的情况下将值传递给孩子。如果您有依赖相同变量的深层嵌套子级,这非常有用。这样您就不必将它们作为道具传递下来,您只需使用useContext 钩子即可抓住它们。下面是一个如何使用 Context 的例子:

    const Endpoint = 'http://localhost:5000/'
    
    const ModelsContext = createContext([])
    
    function ModelsContextProvider({children}) {
      const [models, setModels] = useState([])
      
      return (
        <ModelsContext.Provider value={{models, setModels}}>
          {children}
        </ModelsContext.Provider>
      )
    }
    
    function Models() {
      const { models, setModels } = useContext(ModelsContext)
    
      const updateModels = async () => {
        await fetch(Endpoint + 'models', {
            method: 'GET',
            headers: {
                Accept: 'application/json'
            }
        })
        .then((resp) => resp.json())
        .then(function(data) {
            setModels(data.models)
        })
      }
    
      return (
        <VStack>
            <Button
                size="sm"
                colorScheme='teal'
                variant='solid'
                onClick={updateModels}>
            Get Models List
            </Button>
              <OrderedList>
                {
                    models.map((name) => (
                        <ListItem>
                            {name}
                        </ListItem>
                    ))
                }
              </OrderedList>
        </VStack>
      )
    }
    
    export default function App() {
      return (
        <ModelsContextProvider>
          <Models />
        </ModelsContextProvider>
      );
    }
    

    在上面的示例中,您正在使用状态值设置上下文值。因此,您可以让 useState 挂钩充当上下文的设置器。在您的示例中,您不需要上下文,只需使用 useState 钩子即可。

    const Endpoint = 'http://localhost:5000/'
    
    function Models() {
        const [models, setModels] = React.useState([])
        const updateModels = async () => {
            await fetch(Endpoint + 'models', {
                method: 'GET',
                headers: {
                    Accept: 'application/json'
                }
            })
            .then((resp) => resp.json())
            .then(function(data) {
                setModels(data.models)
            })
        }
    
        return (
            <VStack>
                <Button
                    size="sm"
                    colorScheme='teal'
                    variant='solid'
                    onClick={updateModels}>
                Get Models List
                </Button>
                    <OrderedList>
                    {
                        models.map((name) => (
                            <ListItem>
                                {name}
                            </ListItem>
                        ))
                    }
                    </OrderedList>
    
            </VStack>
        )
    }
    
    export default Models
    

    【讨论】:

    • 我刚刚看到我在Models函数中留下了&lt;ModelsContext.Provider&gt;。这不是必要的。只是想我会告诉你,以防你还没有弄清楚。我编辑了我的答案以反映这一点。我只是复制和粘贴然后重构您的代码并忽略它。
    【解决方案2】:

    您应该将模型包装在&lt;ModelsContext.Provider value={{models}}&gt; 中,然后在模型内部useContext 将返回来自Provider 的值。

    参见doc中的示例

    【讨论】:

    • 我尝试将所有内容都包含在 ModelsContext.Provider value={{models}} 中,但我仍然遇到同样的问题。
    • const {models} = React.useContext(ModelsContext)。对于设置值,请在父组件中使用 useState
    猜你喜欢
    • 1970-01-01
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 2023-04-08
    • 2021-07-04
    • 2019-05-24
    • 1970-01-01
    相关资源
    最近更新 更多