Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在React中使用forwardRef()?_Javascript_Reactjs_Ref - Fatal编程技术网

Javascript 如何在React中使用forwardRef()?

Javascript 如何在React中使用forwardRef()?,javascript,reactjs,ref,Javascript,Reactjs,Ref,我当前在我的React应用程序中收到以下错误: 无法为功能组件提供引用。尝试访问此引用 将失败。您是想使用React.forwardRef()吗 如何使用forwardRef()修复此问题 我的代码如下: const Services: FunctionComponent = (): ReactElement => { const servicesRef = useRef(null); return ( <Layout> <ServicesL

我当前在我的React应用程序中收到以下错误:

无法为功能组件提供引用。尝试访问此引用 将失败。您是想使用React.forwardRef()吗

如何使用forwardRef()修复此问题

我的代码如下:

const Services: FunctionComponent = (): ReactElement => {
  const servicesRef = useRef(null);

  return (
    <Layout>
      <ServicesList ref={servicesRef} />
    </Layout>
  );
};
export default Services;



const ServicesList: React.FunctionComponent = ({ children }: Props) => {
  return (
    <section className="my-24 md:my-32">
      {children && children}
    </section>
  );
};

export default ServicesList;
const服务:FunctionComponent=():ReactElement=>{
const servicesRef=useRef(null);
返回(
);
};
出口默认服务;
const ServicesList:React.FunctionComponent=({children}:Props)=>{
返回(
{children&&children}
);
};
导出默认服务列表;

很好地解释

使用React.forwardRef包装组件,并将ref设置为预期的DOM元素

const FancyButton=React.forwardRef((props,ref)=>( {props.children} )
);

使用
forwardRef
api(再加上
useImperialiveHandle
hook)可以自定义ref在自定义组件中的放置方式和位置。此外,forwardRef是将ref传递给自定义函数组件的唯一方法

首先,了解ref在类组件、函数组件和常规DOM元素上的工作方式不同是很重要的

从:

ref的值因节点类型而异:

  • 在HTML元素上使用ref属性时,在 带有React.createRef()的构造函数接收基础DOM 元素作为其当前属性
  • 当ref属性用于 自定义类组件,ref对象接收装入的实例 组件的当前状态
  • 您不能在上使用ref属性 函数组件,因为它们没有实例
  • 以下是在不同图元类型上使用参照的示例:

    1.DOM元素上的Ref提供对DOM节点本身的引用:
    function AutoFocusInput() {
      const inputRef = useRef(null);
      // This effect runs only once after the component mounts (like componentDidMount)
      useEffect(() => {
        // refs on regular DOM elements (e.g. the "input" tag) have access to the DOM node
        inputRef.current.focus();
      }, []);
      return <input ref={inputRef} />
    }
    
    函数自动聚焦输入(){
    const inputRef=useRef(null);
    //此效果仅在安装组件后运行一次(如componentDidMount)
    useffect(()=>{
    //常规DOM元素(例如“input”标记)上的引用可以访问DOM节点
    inputRef.current.focus();
    }, []);
    返回
    }
    
    2.类组件上的Ref允许我们访问实例及其所有方法和字段:
    class Child extends Component {
      state = {color: "red"}
      toggleColor = () => this.setState({color: this.state.color === "red" ? "blue" : "red"})
      render() {
        return <div style={{backgroundColor: this.state.color}}>yo</div>
      }
    }
    
    class Parent extends Component {
      childRef = createRef();
      handleButtonClicked = () => {
        // refs on class components: hold the class component instance, 
        // allowing us to call its methods!
        this.childRef.current.toggleColor();
      }
      render() {
        return (
          <div>
            <button onClick={this.handleButtonClicked}>toggle color!</button>
            <Child ref={childRef} />
          </div>
        );
      }
    }
    
    类子级扩展组件{
    状态={color:“red”}
    toggleColor=()=>this.setState({color:this.state.color====“红色”?“蓝色”:“红色”})
    render(){
    回程
    }
    }
    类父级扩展组件{
    childRef=createRef();
    把手按钮点击=()=>{
    //类组件参考:保留类组件实例,
    //允许我们调用它的方法!
    this.childRef.current.toggleColor();
    }
    render(){
    返回(
    切换颜色!
    );
    }
    }
    
    3.现在,最后回答你的问题。无法将引用传递给函数组件,因为它们没有实例! 将ref传递给函数组件的唯一方法是使用forwardRef。使用forwardRef时,您可以简单地将ref传递给DOM元素,这样父元素就可以像示例1中那样访问它,或者您可以使用UseImperialiveHandle钩子创建一个包含字段和方法的对象,这类似于eample 2

    3.1只需将ref传递给DOM元素:
    // Only when using forwardRef, the function component receives two arguments, 
    // props and ref (Normally the component only gets the props argument).
    const RedInput = forwardRef((props, ref) => {
      // passing the ref to a DOM element, 
      // so that the parent has a reference to the DOM node
      return <input style={{color: "red"}} {...props} ref={ref} />
    });
    
    function AutoFocusInput() {
      const inputRef = useRef(null);
      // This effect runs only once after the component mounts (like componentDidMount)
      useEffect(() => {
        // ref on function component is forwarded to a regular DOM element, 
        // so now the parent has access to the DOM node including its focus method.
        // Note that the ref usage is the same as a regular 
        // DOM element, like in example 1!
        inputRef.current.focus();
      }, []);
      return <RedInput ref={inputRef} />
    }
    
    //仅当使用forwardRef时,函数组件接收两个参数,
    //props和ref(通常组件只获取props参数)。
    常量RedInput=forwardRef((道具,ref)=>{
    //将ref传递给DOM元素,
    //这样父节点就有了对DOM节点的引用
    返回
    });
    函数AutoFocusInput(){
    const inputRef=useRef(null);
    //此效果仅在安装组件后运行一次(如componentDidMount)
    useffect(()=>{
    //函数组件上的ref被转发到常规DOM元素,
    //因此,现在父节点可以访问DOM节点,包括它的focus方法。
    //请注意,ref用法与常规用法相同
    //DOM元素,如示例1所示!
    inputRef.current.focus();
    }, []);
    返回
    }
    
    3.2将父引用附加到自定义对象: 要将函数或字段附加到ref,就像处理类组件的实例一样,需要使用`useImperialiveHandle`钩子:

    const Child = forwardRef((props, ref) => {
      const [color, setColor] = useState("red");
      // To customize the value that the parent will get in their ref.current: 
      // pass the ref object to useImperativeHandle as the first argument. 
      // Then, whatever will be returned from the callback in the second argument, 
      // will be the value of ref.current. 
      // Here I return an object with the toggleColor method on it, for the parent to use:
      useImperativeHandle(ref, () => ({
        toggleColor: () => setColor(prevColor => prevColor === "red" ? "blue" : "red")
      }));
      return <div style={{backgroundColor: color}}>yo</div>;
    });
    
    
    class Parent extends Component {
      childRef = createRef();
      handleButtonClicked = () => {
        // Ref passed to a function component wrapped in forwardRef.
        // Note that nothing has changed for this Parent component
        // compared with the class component in example 2!
        this.childRef.current.toggleColor();
      }
      render() {
        return (
          <div>
            <button onClick={this.handleButtonClicked}>toggle color!</button>
            <Child ref={childRef} />
          </div>
        );
      }
    }
    
    const Child=forwardRef((props,ref)=>{
    const[color,setColor]=使用状态(“红色”);
    //要自定义父级将在其ref.current中获得的值,请执行以下操作:
    //将ref对象作为第一个参数传递给UseImperializeHandle。
    //然后,在第二个参数中,无论回调返回什么,
    //将是参考电流的值。
    //在这里,我返回一个带有toggleColor方法的对象,供父对象使用:
    使用命令式句柄(参考,()=>({
    toggleColor:()=>setColor(prevColor=>prevColor==“红色”?“蓝色”:“红色”)
    }));
    返回哟;
    });
    类父级扩展组件{
    childRef=createRef();
    把手按钮点击=()=>{
    //Ref传递给封装在forwardRef中的函数组件。
    //请注意,此父组件没有任何更改
    //与示例2中的类组件相比!
    this.childRef.current.toggleColor();
    }
    render(){
    返回(
    切换颜色!
    );
    }
    }
    
    答案取决于您想对ref做什么。有关使用
    forwardRef
    的不同方法,请参阅下面我的详细答案。