【问题标题】:Manage Focus on stateless Components - React管理对无状态组件的关注 - React
【发布时间】:2018-05-24 05:08:15
【问题描述】:

拥有一个容器组件来保存状态。它渲染了许多无状态的组件。

我想访问他们所有的 DOM 节点,所以我可以按需调用focus method

我正在尝试ref 方法,因为它是encouraged by the react documentation

我收到以下错误: Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.

解决此错误的推荐方法是什么? 最好不要使用额外的 dom 元素包装器,例如 exra div。 这是我当前的代码:

容器组件 - 负责渲染无状态组件。

import React, { Component } from 'react';
import StatelessComponent from './components/stateless-component.jsx'

class Container extends Component {
    constructor() {
        super()
        this.focusOnFirst = this.focusOnFirst.bind(this)
        this.state = {
            words: [
                'hello',
                'goodbye',
                'see ya'
            ]
        }
    }
    focusOnFirst() {
        this.node1.focus()
    }
    render() {
        return (
            <div>
                {
                    this.state.words.map((word,index)=>{
                        return <StatelessComponent
                        value={word}
                        ref={node => this[`node${index}`] = node}/>
                    })
                }
                <button onClick={this.focusOnFirst}>Focus on First Stateless Component</button>
            </div>
        )
    }
}

无状态组件 - 为简单起见,只需在 div 中显示文本即可。

import React from 'react';
export default function StatelessComponent(props)  {
    return <div>props.value</div>
}

【问题讨论】:

    标签: javascript reactjs dom


    【解决方案1】:

    无状态(功能)组件不能直接暴露 refs。但是,如果它们的内部组件可以使用 refs,则可以通过 ref forwarding 将无状态组件(父级)的父级(祖父级)的函数作为 ref 传递。将该函数用作 DOM 元素的 ref 目标。现在祖父母可以直接访问 DOM 元素 ref。

    请参阅 React 文档中的 Exposing DOM Refs to Parent Components

    const StatelessComponent = React.forwardRef((props, ref) => (
      <div>
        <input ref={ref} {...props} />
      </div>
    ));
    
    class Container extends React.Component { 
      itemRefs = []
    
      componentDidMount() {
        this.focusOnFirst();
      }
    
      focusOnFirst = () => this.itemRefs[0].focus()
    
      inputRef = (ref) => this.itemRefs.push(ref)
    
      render() {
        return (
          <div>
            <StatelessComponent ref={this.inputRef} />
            <StatelessComponent ref={this.inputRef} />
          </div>
        )
      }
    }
    
    ReactDOM.render(
      <Container />,
      demo
    )
    <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="demo"></div>

    【讨论】:

    【解决方案2】:

    试试这个,基本上你将回调作为 ref 传递给获取输入实例并将其添加到容器拥有的数组的无状态组件

    class Container extends Component {
        constructor() {
            super()
            this._inputs = [];
            this.focusOnFirst = this.focusOnFirst.bind(this)
            this.state = {
                words: [
                    'hello',
                    'goodbye',
                    'see ya'
                ]
            }
        }
        focusOnFirst() {
            this._inputs[0].focus()
        }
    
        refCallback(ref) {
            this._inputs.push(ref)
        }
    
        render() {
            return (
                <div>
                    {
                        this.state.words.map((word,index)=>{
                            return <StatelessComponent
                            value={word}
                            refCallback={this.refCallback}/>
                        })
                    }
                    <button onClick={this.focusOnFirst}>Focus on First Stateless Component</button>
                </div>
            )
        }
    }
    

    无状态的也被修改了一点

    function StatelessComponent({refCallback, value})  {
        return <input ref={refCallback} value={value}/>
    }
    

    Here's a working plunker

    【讨论】:

      猜你喜欢
      • 2019-09-12
      • 1970-01-01
      • 2022-10-24
      • 2022-12-17
      • 2020-07-13
      • 2019-05-08
      • 2017-09-16
      • 2019-11-28
      • 2017-11-26
      相关资源
      最近更新 更多