使用参考

时间:2019-08-27 15:05:23

标签: javascript reactjs react-hooks

我要改用Hooks构建组件,而我正努力用useRef()设置引用

父项(当前仅将引用添加到一个组件,因为我想确保在将功能扩展到其他组件之前可以正常工作)

export default function UserPanels({ selected_client } ) {
    const classes = useStyles();
    const [value, setValue] = useState(0);
    const container = useRef( null );

    function handleChange(event, newValue) {
        setValue(newValue);
        container.current.displayData();
    }

    return (
        <div className={classes.root}>
            <UserTabs
                value={value}
                onChange={handleChange}
                indicatorColor="primary"
                textColor="primary"
                variant="fullWidth"
                aria-label="full width tabs example"
            >
                <Tab label='Service User' {...a11yProps(0)} />
                <Tab label='Care Plan' {...a11yProps(1)} />
                <Tab label='Contacts' {...a11yProps(2)} />
                <Tab label='Property' {...a11yProps(3)} />
                <Tab label='Schedule' {...a11yProps(4)} />
                <Tab label='Account' {...a11yProps(5)} />
                <Tab label='Invoices' {...a11yProps(6)} />
                <Tab label='Notes' {...a11yProps(7)} />
                <Tab label='eMAR' {...a11yProps(8)} />
            </UserTabs>
            <TabPanel value={value} index={0}>
                <UserDetailsContainer
                    selected_client={ selected_client }
                />
            </TabPanel>
            <TabPanel value={value} index={1}>
                Care Plan
            </TabPanel>
            <TabPanel value={value} index={2}>
                <ContactsContainer
                    ref={ container }
                    selected_client={ selected_client }
                />
            </TabPanel>
            <TabPanel value={value} index={3}>
                Property
            </TabPanel>
            <TabPanel value={value} index={4}>
                Schedule
            </TabPanel>
            <TabPanel value={value} index={5}>
                Account
            </TabPanel>
            <TabPanel value={value} index={6}>
                Invoices
            </TabPanel>
            <TabPanel value={value} index={7}>
                Notes
            </TabPanel>
            <TabPanel value={value} index={8}>
                eMAR
            </TabPanel>
        </div>
    );
}

孩子:

export default function ContactsContainer( props ) {
    const [ state, setState ] = useState({
        contact_records: contacts,
        data_ready: true
    });

    function displayData() {
        console.log( 'display time' );
    }

    if ( !state.data_ready ) return null

    return (
        <>
            {
                state.contact_records.map( ( contact ) => {
                    return <ContactRecord contact={ contact } />
                } )
            }
        </>
    )
}

基本上,我正在尝试从父级调用子级函数,但ref.current的计算结果为null,并且在调用handleChange()时收到错误container.current is null,定期看到错误Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

请注意,我已经测试过forwardRef

<ContactsContainer
    ref={ container }
    selected_client={ selected_client }
 />

并且,尽管这消除了错误,但不能解决问题。我从来没有在类组件上使用ref的问题,但这里似乎缺少了一些东西。

2 个答案:

答案 0 :(得分:2)

首先,请不要过度使用refsreact doc)。您不能直接调用子组件的功能来控制子组件(老实说,您不能使用功能组件来做到这一点)。

如果需要在子级中显示某些内容,则必须在父级组件中准备数据并通过道具传递该数据。儿童应尽可能简单。他们应该得到道具并显示一些数据。

在父母中:

const [value, setValue] = useState(0);
const [time, setTime] = useState(null);
function handleChange(event, newValue) {
    setValue(newValue);
    setTime('display time');
}

return (
    ....
    <ContactsContainer
        time={time}
        selected_client={ selected_client }
     />
    ....
)

如果在道具更改时需要在孩子中产生一些副作用(例如,进行HTTP调用,调度Redux操作),则必须使用useEffect钩子。

在父母中:

<ContactsContainer
    value={value}
    selected_client={ selected_client }
 />

在儿童中:

useEffect(() => {
  console.log('display time action');
}, [props.value]);

答案 1 :(得分:0)

您可以将 ref 作为道具传递:

// ...
const infoRef=useRef(null)
useEffect(()=>{
    if(infoRef.current) infoRef.current()
},[])
return <ChildComponent infoRef={infoRef} />

然后在孩子:

useEffect(()=>{
    infoRef.current=childFunctionToExecuteInParent
},[])