Крючки можно использовать только внутри функциональных компонентов, и их нельзя использовать в качестве конструкторов. Стандартный ответ будет состоять в том, чтобы переместить обработку состояния в компонент упаковки (App) и передать состояние EventDay:
const { useState, useCallback, useEffect } = React;
const EventDay = ({ events }) => events.map((o, i) => (<li key={i}>{o.eventName}</li>));
function App() {
const [events, setEvents] = useState([{eventName: "first event"}]);
const addEvent = useCallback(eventCard => setEvents(prevEvents => [...prevEvents, eventCard]), []);
useEffect(() => {
setTimeout(() => {
addEvent({eventName: "new event"});
}, 1000);
}, [addEvent])
return (
<ul>
<EventDay events={events} />
</ul>
);
}
ReactDOM.render(
<App />,
root
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Однако, если вам нужно получить функцию от компонента, вы можете использовать ref
с крючком useImperativeHandle
:
const { forwardRef, useState, useImperativeHandle, useRef, useEffect } = React;
const EventDay = forwardRef((props, ref) => {
const [events, setEvents] = useState([{eventName: "first event"}]);
useImperativeHandle(ref, () => ({
addEvent(eventCard) {
setEvents(prevEvents => [...prevEvents, eventCard]);
}
}));
return events.map((o, i) => (<li key={i}>{o.eventName}</li>));
});
function App() {
const eventRef = useRef();
useEffect(() => {
setTimeout(() => {
eventRef.current.addEvent({eventName: "new event"});
}, 1000);
}, [])
return (
<ul>
<EventDay ref={eventRef} />
</ul>
);
}
ReactDOM.render(
<App />,
root
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>