#javascript #reactjs #react-context #react-dnd
Вопрос:
Я пытался узнать о контексте react и о том, как изменить его из дочернего компонента, но я продолжаю получать странные ошибки
здесь я создаю контекст массива и пытаюсь изменить его при отбрасывании элемента из дочернего элемента, но это приводит к ошибке TypeError: context.push не является функцией
import { React, createContext, useContext } from "react";
import { useState } from "react";
import { useDrag, useDrop } from "react-dnd";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
function WebsiteBody(props) {
const [context, add_to_context] = useContext(WebsiteContext);
const [{ droppedItem, didDrop, isOver, canDrop }, drop] = useDrop(() => ({
accept: "card",
drop: () => ({
name: "body",
}),
collect: (monitor) => ({
droppedItem: monitor.getItem(),
didDrop: monitor.didDrop(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
}));
if (didDrop) {
add_to_context(droppedItem.item);
}
return (
<div
ref={drop}
w="100vw"
h="100vh"
backgroundColor="yellow"
display="flex"
>
{dropped_items.map((item) => item.name)}
</Box>
);
}
const MyContext = createContext([]);
function App(props) {
const [context, setContext] = useState([]);
function add_item(item) {
setContext(context.push(item));
}
return (
<DndProvider backend={HTML5Backend}>
<MyContext.Provider value={[context, add_item]}>
<WebsiteBody></WebsiteBody>
</MyContext.Provider>
</DndProvider>
);
}
export default App;
Комментарии:
1. Можете ли вы добавить трассировку ошибки стека в свой вопрос?
2.
context
это переменная только для чтения, если вы попытаетесь ее изменить, это не сработает, попробуйте[...context, item]
вместоcontext.push(item)
Ответ №1:
В вашем коде есть три проблемы:
- Мутирующие состояния непосредственно с помощью
Array.push
ContextType
s разные. Одно естьMyContext
, другое естьWebsiteContext
.- Недопустимое значение по умолчанию предоставляется для
createContext
Измените код следующим образом:
WebsiteContext.js
export default React.createContext([
[], // default value for context value
() => {} // default value for addItem
]);
App.js
import WebsiteContext from './WebsiteContext';
const [context, setContext] = useContext([]);
const addItem = (item) => {
setContext(old => [...old, item]);
};
<WebsiteContext.Provider value={[context, addItem]}>
</WebsiteContext.Provider>
WebsiteBody.js
import WebsiteContext from './WebsiteContext';
const [context, add_to_context] = useContext(WebsiteContext);