如何从其父组件访问自定义的React组件函数?

时间:2020-04-28 21:35:12

标签: javascript reactjs react-hooks react-component

我想创建一个组件的新实例,然后在该组件内使用一个函数添加一个新对象。没有任何东西对我有用。这是我的代码:

包含列表的组件和添加新eventCard的功能

function EventDay (props) { 

   const [ events, setEvents ] = useState([{eventName: "first event"}]);

   function addEvent(eventCard) {
      setEvents( prevEvents => [...prevEvents, eventCard]);
   }

   return console.log(events);
}

export default EventDay;

要访问addEvent函数的组件

import EventDay from "./EventDay"

function App() {
   const eventDay = new EventDay();

   eventDay.addEvent({eventName: "New Event"});

}

我收到错误消息addEvent不是函数。我尝试导出它,但由于它是函数中的一个函数,所以无法导出。如何实现以上目标?

1 个答案:

答案 0 :(得分:1)

挂钩只能在功能组件内部使用,而不能用作构造函数。标准答案是将状态处理移至包装组件(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>

但是,如果必须从组件中获取功能,则可以将refuseImperativeHandle挂钩一起使用:

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>