【问题标题】:SpinButton: public property 'value' is undefined and public method 'focus()' is not a functionSpinButton:公共属性“值”未定义,公共方法“焦点()”不是函数
【发布时间】:2019-05-14 11:49:39
【问题描述】:

我最近开始使用 reactjs、typescript 和 Office UI Fabric。但我已经在为面料中的一种成分而苦苦挣扎。 在此示例中,我有一个简单的 Product 组件,其中包含一个 SpinButton 和一个 DefaultButton。 单击 DefaultButton 时,我想获取 SpinButton 的值并将焦点设置在它上面。 为了获得 ISpinButton 接口成员,我使用了 React.RefObject 的引用。 我的代码如下所示:

import * as React from 'react';

import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { SpinButton } from 'office-ui-fabric-react/lib/SpinButton';

class Product extends React.Component<{}, {}> {

    private spbStockRef: React.RefObject<SpinButton> = React.createRef<SpinButton>();

    public render(): JSX.Element {
        return (
            <React.Fragment>
                <SpinButton
                    ref={this.spbStockRef}
                    defaultValue="0"
                    label={'Stock '}
                    min={0}
                    max={99999}
                    step={1}
                    onFocus={() => console.log('onFocus called')}
                    onBlur={() => console.log('onBlur called')} />
                <DefaultButton onClick={this.onButtonClick} />
            </React.Fragment>)
    }

    private onButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => {
        const node = this.spbStockRef.current!;

        if (node) {
            console.log(node.value);
            node.focus();
        }
    }
}
export default Product;

在 onButtonClick 内部,Visual Studio 的智能感知建议在节点变量上同时使用“value”和“focus()”,因此应该可以访问实际的 ISpinButton 成员。

但是当单击按钮时,console.log(node.value) 输出 undefined 并且在 node.focus() 上引发 TypeError: TypeError: node.focus 不是函数。 我还想提一下,console.log(node) 会输出一个正确的实例化对象,因此 ref 可以正常工作。

知道我在这里做错了什么吗? 在 SpinButton 组件的示例中,也没有任何内容指出如何进行这项工作。

https://developer.microsoft.com/en-us/fabric?example=#/components/spinbutton

谢谢

【问题讨论】:

    标签: reactjs typescript office-ui-fabric


    【解决方案1】:

    对于fabric-ui,要将引用附加到内部元素而不是组件,您可以使用componentRef

    这将为SpinButton 编写代码:

    <SpinButton
       componentRef={this.spbStockRef}
       defaultValue="0"
       label={'Stock '}
       min={0}
       max={99999}
       step={1}
    />
    

    const { SpinButton } = window.Fabric;
    
    class App extends React.Component {
      spinBtn = React.createRef();
      componentDidMount() {
        this.spinBtn.current.focus();
      }
      render() {
        return (
          <SpinButton
            defaultValue="0"
            label={'Basic SpinButton:'}
            min={0}
            max={100}
            step={1}
            componentRef={this.spinBtn}
            iconProps={{ iconName: 'IncreaseIndentLegacy' }}
          />
        );
      }
    }
    
    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
    <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css">
    <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>
    <script src="//unpkg.com/office-ui-fabric-react/dist/office-ui-fabric-react.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 感谢您的建议,但这不适用于我的打字稿。如果我使用 componentRef 而不是 ref,我会收到以下类型不匹配错误:(TS) Type 'RefObject' is notassignable to type '(component?: ISpinButton | null | undefined) => void'。类型 'RefObject' 不匹配签名 '(component?: ISpinButton | null | undefined): void'。
    • 所以它只接受一个方法而不是一个 RefObject,正如我所期望的那样:来自文档link ISpinButtonProps interface / componentRef (component?: ISpinButton | null) => void
    • 我不确定为什么打字稿不起作用,因为您可以看到代码正常工作。可能与打字有关
    • 是的,确实如此。我不知道为什么在 SpinButton 的情况下 componentRef 必须是方法而不是 RefObject。
    • 为了清楚起见,当我运行您的代码 sn-p 时,我并没有真正看到焦点设置在 SpinButton 上,所以我不确定它是否真的有效?
    【解决方案2】:

    受到银翼男孩的启发,我找到了一种解决方法。我没有为 RefObject 使用特定类型,而是将其声明为 any,然后我就可以使用 componentRef。 所以基本上我必须重写 componentRef 所需的类型 (component?: ISpinButton | null) => void 才能使其工作。我不知道这是否应该报告为错误。

    import * as React from 'react';
    
    import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
    import { SpinButton } from 'office-ui-fabric-react/lib/SpinButton';
    
    class Product extends React.Component<{}, {}> {
    
        private spbStockRef: any = React.createRef();
    
        public render(): JSX.Element {
            return (
                <React.Fragment>
                    <SpinButton
                        componentRef={this.spbStockRef}
                        defaultValue="0"
                        label={'Stock '}
                        min={0}
                        max={99999}
                        step={1}
                        onFocus={() => console.log('onFocus called')}
                        onBlur={() => console.log('onBlur called')} />
                    <DefaultButton onClick={this.onButtonClick} />
                </React.Fragment>)
        }
    
        private onButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => {
            const node = this.spbStockRef.current!;
    
            if (node) {
                console.log(node.value);
                node.focus();
            }
        }
    }
    export default Product;
    

    【讨论】:

      猜你喜欢
      • 2021-08-11
      • 2013-02-13
      • 2018-12-12
      • 2020-09-22
      • 1970-01-01
      • 2014-01-26
      • 2011-04-19
      • 2018-11-12
      • 1970-01-01
      相关资源
      最近更新 更多