#javascript #reactjs #chakra-ui
#javascript #reactjs #чакра-пользовательский интерфейс
Вопрос:
Я пытаюсь создать такую кнопку, чтобы при нажатии изменялся контекст реакции. То есть мой контекст состоит только из списка строк, который заполняется при успешном выполнении запроса 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
переменная остается неопределенной внутри <OrderedList />
блока, даже если я определил контекстный блок React Provider.
Фактическая ошибка, которую я получаю, такова: «Ошибка типа: модели не определены» в позиции <OrderedList>
.
Заранее благодарю вас!
Ответ №1:
Вы неправильно используете контекст. Контекст предназначен для передачи значений дочерним элементам без детализации реквизита. Это отлично подходит, если у вас есть глубоко вложенные дочерние элементы, которые полагаются на одни и те же переменные. Таким образом, вам не нужно передавать их в качестве реквизитов, вы можете просто захватить их с помощью useContext
хука. Вот пример того, как использовать контекст:
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
Комментарии:
1. Я только что увидел, что я оставил функцию
<ModelsContext.Provider>
в моделях. В этом нет необходимости. Просто подумал, что я дам вам знать, если вы еще не поняли этого. Я отредактировал свой ответ, чтобы отразить это. Я просто копировал и вставлял, а затем рефакторил ваш код и пропустил его.
Ответ №2:
Вы должны обернуть модели <ModelsContext.Provider value={{models}}>
, а затем внутри моделей useContext
будет возвращено значение от поставщика.
Смотрите Пример в документе
Комментарии:
1. Я попытался обернуть все внутри
ModelsContext.Provider value={{models}}
, но у меня все та же проблема.2. const {models} = React.useContext(ModelsContext). Для установки значений используйте
useState
в родительском компоненте