使用forwardRef“不能给功能组件提供参考”并连接到功能组件中

时间:2020-05-11 09:11:10

标签: reactjs typescript redux react-redux react-hooks

父组件(我删除了一些不相关的代码):

import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react
import InputItem from 'src/components/InputItem'

 let tokenRef = useRef(null)
 return (
         <InputItem
           ref={tokenRef}
           placeHolder="xxxx"
         />
 )
}
const mapStateToProps = ({ form }) => {
 return {
   form
 }
}
const mapDispatchToProps = (dispatch, props) => {
 return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(Header)

子功能组件(我删除了一些不相关的代码):

import React, {
  useState,
  useRef,
  useMemo,
  forwardRef,
  useImperativeHandle,
  Ref
} from 'react'
import './index.less'
import { connect } from 'react-redux'
interface IOwnProps {
  placeHolder?: string
}
interface IStateProps {
  form: any
}
interface IDispatchProps {
}
type IProps = IStateProps & IOwnProps & IDispatchProps
const InputItem = forwardRef((props: IProps, ref: Ref<any>) => {
  const {
    placeHolder,
  } = props
  const ipt = useRef(null)

  useImperativeHandle(ref, () => {
    return {
      value: ipt.current.value,
      focus: () => ipt.current.focus()
    }
  })

  return (
    <div className="input-item" style={style}>
          <input
            type="text"
            placeholder={placeHolder}
            ref={ipt}
          ></input>
    </div>
  )
})
const mapStateToProps = ({ form }) => {}
const mapDispatchToProps = (dispatch, props) => {}
export default connect(mapStateToProps, mapDispatchToProps)(InputItem)

我收到一条警告,提示我不能在函数组件中使用ref。但是,我确实在子组件中使用了forwardRef来避免此类问题,并且将useRef的值更改为被包装的组件仍然无效。

警告:不能为功能组件提供引用。尝试访问 该裁判将失败。您是要使用React.forwardRef()吗?

1 个答案:

答案 0 :(得分:3)

您可以添加{ forwardRef : true }选项:

export default connect(
  mapStateToProps, 
  mapDispatchToProps,
  null,
  { forwardRef: true } // this is the important line
)(InputItem)

const Comp = React.forwardRef(({counter, increment}, ref) => (
  <div ref={ref}>
    <p>Comp. counter state: {counter}</p>
    <button onClick={increment}>Increment</button>
  </div>
));

// a simple implementation with increment counter action
const store = Redux.createStore(s => s + 1, 0);
const mapStateToProps = state => ({ counter: state });
const mapDispatchToProps = dispatch => ({
  increment: () => dispatch({type: "increment"})
});

const ConnectedComp = ReactRedux.connect(
  mapStateToProps,
  mapDispatchToProps,
  null,
  { forwardRef: true } // this is the important line
)(Comp);

const App = () => {
  const setBlueColor = () => ref.current.style.color = "blue"
  const ref = React.useRef();
  return (
    <ReactRedux.Provider store={store}>
      <ConnectedComp ref={ref} />
      <button onClick={setBlueColor}>Set blue color</button>
    </ReactRedux.Provider>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js" integrity="sha256-JuJho1zqwIX4ytqII+qIgEoCrGDVSaM3+Ul7AtHv2zY=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js" integrity="sha256-7nQo8jg3+LLQfXy/aqP5D6XtqDQRODTO18xBdHhQow4=" crossorigin="anonymous"></script>