रीस्क्रिप्ट में टाइपस्क्रिप्ट के साथ कैसे उपयोग करें


139

मैं React के साथ टाइपस्क्रिप्ट का उपयोग कर रहा हूं। मुझे यह समझने में परेशानी हो रही है कि रेफरी द्वारा संदर्भित प्रतिक्रिया नोड्स के संबंध में स्टैटिक टाइपिंग और इंटेलीसेंस प्राप्त करने के लिए रेफरी का उपयोग कैसे करें। मेरा कोड इस प्रकार है।

import * as React from 'react';

interface AppState {
    count: number;
}

interface AppProps {
    steps: number;
}

interface AppRefs {
    stepInput: HTMLInputElement;
}

export default class TestApp extends React.Component<AppProps, AppState> {

constructor(props: AppProps) {
    super(props);
    this.state = {
        count: 0
    };
}

incrementCounter() {
    this.setState({count: this.state.count + 1});
}

render() {
    return (
        <div>
            <h1>Hello World</h1>
            <input type="text" ref="stepInput" />
            <button onClick={() => this.incrementCounter()}>Increment</button>
            Count : {this.state.count}
        </div>
    );
}}

जवाबों:


183

यदि आप React 16.3+ का उपयोग कर रहे हैं, तो Refs बनाने का सुझाया तरीका उपयोग कर रहा है React.createRef()

class TestApp extends React.Component<AppProps, AppState> {
    private stepInput: React.RefObject<HTMLInputElement>;
    constructor(props) {
        super(props);
        this.stepInput = React.createRef();
    }
    render() {
        return <input type="text" ref={this.stepInput} />;
    }
}

जब घटक की गणना करता है, तो refविशेषता की currentसंपत्ति को संदर्भित घटक / DOM तत्व को सौंपा जाएगा और nullजब इसे अनमाउंट किया जाएगा तो इसे वापस सौंपा जाएगा । इसलिए, उदाहरण के लिए, आप इसका उपयोग कर सकते हैं this.stepInput.current

अधिक जानकारी के लिए RefObject, @ apiblofbart का उत्तर देखें या PR createRef() को इसमें जोड़ा गया था।


यदि आप प्रतिक्रिया के पहले संस्करण (<16.3) का उपयोग कर रहे हैं या जब refs सेट और परेशान होते हैं, तो अधिक बारीक नियंत्रण की आवश्यकता होती है, आप "कॉलबैक रिफ्स" का उपयोग कर सकते हैं ।

class TestApp extends React.Component<AppProps, AppState> {
    private stepInput: HTMLInputElement;
    constructor(props) {
        super(props);
        this.stepInput = null;
        this.setStepInputRef = element => {
            this.stepInput = element;
        };
    }
    render() {
        return <input type="text" ref={this.setStepInputRef} />
    }
}

जब घटक माउंट करता है, तो रिएक्ट refDOM तत्व के साथ कॉलबैक को कॉल करेगा, और nullअनमाउंट होने पर इसे कॉल करेगा । इसलिए, उदाहरण के लिए, आप इसे केवल उपयोग करके देख सकते हैं this.stepInput

refइनलाइन फ़ंक्शन ( इस उत्तर के पिछले संस्करण में) के विपरीत वर्ग पर कॉलबैक को एक सीमित विधि के रूप में परिभाषित करके , आप अपडेट के दौरान दो बार कॉलबैक से बचने से बच सकते हैं ।


वहाँ हुआ करता था एक API जहां ref(देखें विशेषता कोई स्ट्रिंग था अक्षर पटेल की जवाब ), लेकिन की वजह से कुछ मुद्दों , स्ट्रिंग refs दृढ़ता से हतोत्साहित किया जाता है और अंत में निकाल दिया जाएगा।


22.3, 2018 को संपादित करने का नया तरीका रिएक्ट 16.3 में जोड़ने का है। @Aphewofbart को इंगित करने के लिए धन्यवाद कि एक नया तरीका था।


ध्यान दें यह पसंदीदा तरीका है। refsवर्ग विशेषता के साथ नीचे दिए गए उदाहरणों को आगामी प्रतिक्रिया संस्करणों में पदावनत किया जाएगा।
जिमी पजाला

1
कृपया ध्यान दें कि यह पहले से ही एक पुराना तरीका है :) वर्तमान में React.createRef () का उपयोग करना है
apiblofbart

@apiblofbart सिर के लिए धन्यवाद। नए तरीके को शामिल करने के लिए उत्तर का अद्यतन करें।
जेफ बोवेन

2
मुझे आपके उत्तर में टाइपस्क्रिप्ट के बारे में कुछ भी नहीं दिखाई दे रहा है, मैं एक और उत्तर
जोड़ूंगा

ओह। मेरे मूल उत्तर में टाइपस्क्रिप्ट था लेकिन इसे नए में शामिल करना भूल गया। इसे वापस जोड़ा और आपके उत्तर से भी जुड़ा। धन्यवाद।
जेफ बोवेन

30

एक तरीका (जो मैं कर रहा था ) मैन्युअल रूप से सेटअप करना है:

refs: {
    [string: string]: any;
    stepInput:any;
}

फिर आप इसे एक अच्छे गेटर फ़ंक्शन (जैसे यहाँ ) में भी लपेट सकते हैं :

stepInput = (): HTMLInputElement => ReactDOM.findDOMNode(this.refs.stepInput);

1
साभार @basarat मैंने आपके समाधान की कोशिश की, लेकिन मुझे यह त्रुटि मिल रही है 'टाइप तत्व HTMLInputElement टाइप करने योग्य नहीं है। संपत्ति स्वीकार टाइप एलीमेंट में गायब है ''
अक्षर पटेल

प्रतिक्रिया-प्रधान परिभाषाओं के नए संस्करण के साथ एक समस्या हो सकती है। इस बीच में
मुखरता का

जाहिर anyहै यहां अनिवार्य नहीं है। सबसे अधिक उदाहरण मैं उपयोग देखता हूं HTMLInputElement। बस स्पष्ट बताते हुए, लेकिन यदि आपका रेफ एक रिएक्ट घटक (यानी PeoplePicker) पर है, तो आप उस घटक का उपयोग टाइपिंग प्राप्त करने के लिए कर सकते हैं।
जो मार्टेला

24

चूंकि रिएक्ट 16.3 रेफरी को जोड़ने का तरीका है, इसलिए React.createRef का उपयोग करना चाहिए क्योंकि जेफ बोवेन ने अपने जवाब में कहा था। हालाँकि आप बेहतर रेफरी के लिए टाइपस्क्रिप्ट का लाभ उठा सकते हैं।

अपने उदाहरण में आप इनपुट तत्व पर रेफरी का उपयोग कर रहे हैं। इसलिए वे कहते हैं कि मैं यह करूंगा:

class SomeComponent extends React.Component<IProps, IState> {
    private inputRef: React.RefObject<HTMLInputElement>;
    constructor() {
        ...
        this.inputRef = React.createRef();
    }

    ...

    render() {
        <input type="text" ref={this.inputRef} />;
    }
}

ऐसा करने से जब आप उस रेफरी का उपयोग करना चाहते हैं तो आपके पास सभी इनपुट विधियों तक पहुंच होती है:

someMethod() {
    this.inputRef.current.focus(); // 'current' is input node, autocompletion, yay!
}

आप इसे कस्टम घटकों पर भी उपयोग कर सकते हैं:

private componentRef: React.RefObject<React.Component<IProps>>;

और फिर, उदाहरण के लिए, सहारा तक पहुंच:

this.componentRef.current.props; // 'props' satisfy IProps interface

17

संपादित करें: यह टाइपस्क्रिप्ट के साथ रेफ का उपयोग करने का सही तरीका नहीं है। जेफ बोवेन के उत्तर को देखें और अपनी दृश्यता बढ़ाने के लिए इसे बढ़ाएं।

समस्या का उत्तर मिला। वर्ग के अंदर नीचे के रूप में रेफ का उपयोग करें।

refs: {
    [key: string]: (Element);
    stepInput: (HTMLInputElement);
}

सही दिशा में इशारा करने के लिए @basarat धन्यवाद।


2
मैं अभी भी प्राप्त Property 'stepInput' does not exist on type '{ [key: string]: Component<any, any> | Element; }'कर रहा हूं , जब पहुंचने की कोशिश कर रहा हूं this.refs.stepInput
निक सुमीको

@NikSumeiko, आपको वह त्रुटि मिल रही refsथी क्योंकि आपके ऑब्जेक्ट में केवल [key: string]प्रविष्टि थी।
जो मार्टेला

9

React.createRef (कक्षा के घटक)

class ClassApp extends React.Component {
  inputRef = React.createRef<HTMLInputElement>();
  
  render() {
    return <input type="text" ref={this.inputRef} />
  }
}

नोट: पुराने स्ट्रिंग Refs लीगेसी API को यहाँ स्वीकार कर रहा है ...


React.useRef (हुक / फ़ंक्शन घटक)

डोम नोड्स के लिए पढ़ें
const FunctionApp = () => {
  const inputRef = React.useRef<HTMLInputElement>(null) // note the passed in `null` arg
  return <input type="text" ref={inputRef} />
}
मनमाने ढंग से संग्रहीत मूल्यों के लिए म्यूचुअल रेफरी :
const FunctionApp = () => {
  const renderCountRef = useRef(0)
  useEffect(() => {
    renderCountRef.current += 1
  })
  // ... other render code
}

नोट: Do प्रारंभ नहीं useRefके साथ nullइस मामले में। यह renderCountRefटाइप करेगा readonly(देखें) उदाहरण )। यदि आपको प्रारंभिक मूल्य के रूप में प्रदान करने की आवश्यकता हैnull , तो यह करें:

const renderCountRef = useRef<number | null>(null)

कॉलबैक रिफ्स (दोनों के लिए काम)

// Function component example 
const FunctionApp = () => {
  const handleDomNodeChange = (domNode: HTMLInputElement | null) => {
    // ... do something with changed dom node.
  }
  return <input type="text" ref={handleDomNodeChange} />
}

खेल का मैदान का नमूना


बीच क्या अंतर है useRef() as MutableRefObject<HTMLInputElement>और useRef<HTMLInputElement>(null)?
ksav

2
अच्छा सवाल - की currentसंपत्ति को MutableRefObject<HTMLInputElement>संशोधित किया जा सकता है, जबकि चिह्नित के साथ useRef<HTMLInputElement>(null)एक RefObjectप्रकार बनाता है । पूर्व का उपयोग किया जा सकता है, यदि आपको अपने आप को refs में current DOM नोड्स बदलने की आवश्यकता है, जैसे कि बाहरी लाइब्रेरी के साथ संयोजन में। यह भी बिना लिखा जा सकता है : । अधिकांश मामलों में उपयोग किए गए रिएक्ट प्रबंधित डोम नोड्स के लिए उत्तरार्द्ध एक बेहतर विकल्प है। रिएक्ट स्वयं ही refs में नोड्स को संग्रहीत करता है और आप इन मानों को बदलने के बारे में सोचना नहीं चाहते हैं। currentreadonlyasuseRef<HTMLInputElement | null>(null)
ford04

1
स्पष्टीकरण के लिए धन्यवाद।
ksav

7

यदि आप उपयोग कर रहे हैं React.FC, तो HTMLDivElementइंटरफ़ेस जोड़ें :

const myRef = React.useRef<HTMLDivElement>(null);

और इसे निम्नलिखित की तरह उपयोग करें:

return <div ref={myRef} />;

1
धन्यवाद। जो भी इस पार आता है उसके लिए एक और टिप है एलिमेंट को चेक करना। यह उदाहरण एक DIV तत्व के उपयोग को संदर्भित करता है। उदाहरण के लिए एक फॉर्म का उपयोग होगा - const formRef = React.useRef <HTMLFormElement> (नल);
निक टारस

1
शुक्रिया शुक्रिया शुक्रिया शुक्रिया शुक्रिया शुक्रिया शुक्रिया धन्यवाद।
एम्बुलेंस

2

कॉलबैक शैली ( https://facebook.github.io/react/docs/refs-and-the-dom.html ) का उपयोग करने के लिए रिएक्ट के दस्तावेज़ीकरण पर अनुशंसित के रूप में आप वर्ग पर एक संपत्ति के लिए एक परिभाषा जोड़ सकते हैं:

export class Foo extends React.Component<{}, {}> {
// You don't need to use 'references' as the name
references: {
    // If you are using other components be more specific than HTMLInputElement
    myRef: HTMLInputElement;
} = {
    myRef: null
}
...
 myFunction() {
    // Use like this
    this.references.myRef.focus();
}
...
render() {
    return(<input ref={(i: any) => { this.references.myRef = i; }}/>)
}

1

एक पूर्ण उदाहरण को खोना, यहाँ प्रतिक्रिया और टाइपस्क्रिप्ट के साथ काम करते समय उपयोगकर्ता इनपुट प्राप्त करने के लिए मेरी छोटी परीक्षण स्क्रिप्ट है। अन्य टिप्पणियों और इस लिंक पर आंशिक रूप से आधारित https://medium.com/@basarat/strongly-typed-refs-for-react-typescript-9a07419f807#.cdrghertm

/// <reference path="typings/react/react-global.d.ts" />

// Init our code using jquery on document ready
$(function () {
    ReactDOM.render(<ServerTime />, document.getElementById("reactTest"));
});

interface IServerTimeProps {
}

interface IServerTimeState {
    time: string;
}

interface IServerTimeInputs {
    userFormat?: HTMLInputElement;
}

class ServerTime extends React.Component<IServerTimeProps, IServerTimeState> {
    inputs: IServerTimeInputs = {};

    constructor() {
        super();
        this.state = { time: "unknown" }
    }

    render() {
        return (
            <div>
                <div>Server time: { this.state.time }</div>
                <input type="text" ref={ a => this.inputs.userFormat = a } defaultValue="s" ></input>
                <button onClick={ this._buttonClick.bind(this) }>GetTime</button>
            </div>
        );
    }

    // Update state with value from server
    _buttonClick(): void {
    alert(`Format:${this.inputs.userFormat.value}`);

        // This part requires a listening web server to work, but alert shows the user input
    jQuery.ajax({
        method: "POST",
        data: { format: this.inputs.userFormat.value },
        url: "/Home/ServerTime",
        success: (result) => {
            this.setState({ time : result });
        }
    });
}

}


1

टाइपस्क्रिप्ट उपयोगकर्ता के लिए कोई निर्माता की आवश्यकता नहीं है।

...

private divRef: HTMLDivElement | null = null

getDivRef = (ref: HTMLDivElement | null): void => {
    this.divRef = ref
}

render() {
    return <div ref={this.getDivRef} />
}

...


0

रिएक्ट टाइप परिभाषा से

    type ReactInstance = Component<any, any> | Element;
....
    refs: {
            [key: string]: ReactInstance
    };

तो आप का पालन के रूप में आप refs तत्व का उपयोग कर सकते हैं

stepInput = () => ReactDOM.findDOMNode(this.refs['stepInput']);

रेफरी इंडेक्स के पुनर्वितरण के बिना।

जैसा कि @manakor ने उल्लेख किया है कि आप त्रुटि प्राप्त कर सकते हैं

संपत्ति 'stepInput' प्रकार पर मौजूद नहीं है '{[कुंजी: स्ट्रिंग]: घटक | तत्व; }

यदि आप रिफ़ाइन करते हैं तो (आपके द्वारा उपयोग किए जाने वाले आईडीई और टीएस संस्करण पर निर्भर करता है)


0

बस एक अलग दृष्टिकोण जोड़ने के लिए - आप बस अपना रेफरी डाल सकते हैं, कुछ इस तरह:

let myInputElement: Element = this.refs["myInput"] as Element

0

मैं हमेशा ऐसा करता हूं, उस मामले में एक रेफरी को हथियाने के लिए

let input: HTMLInputElement = ReactDOM.findDOMNode<HTMLInputElement>(this.refs.input);


इनपुट दें: HTMLInputElement = ReactDOM.findDOMNode <HTMLInputElement> (यह। इनपुट []]);
user2662112

0

यदि आप अपने अग्रेषित करने के लिए अभ्यस्त ref, Props इंटरफ़ेस में आप RefObject<CmpType>से प्रकार का उपयोग करने की आवश्यकता हैimport React, { RefObject } from 'react';


0

तत्वों की एक सरणी होने पर इसे कैसे करना है, इसकी तलाश करने वालों के लिए:

const textInputRefs = useRef<(HTMLDivElement | null)[]>([])

...

const onClickFocus = (event: React.BaseSyntheticEvent, index: number) => {
    textInputRefs.current[index]?.focus()
};

...

{items.map((item, index) => (
    <textInput
        inputRef={(ref) => textInputs.current[index] = ref}
    />
    <Button
        onClick={event => onClickFocus(event, index)}
    />
}

-1
class SelfFocusingInput extends React.Component<{ value: string, onChange: (value: string) => any }, {}>{
    ctrls: {
        input?: HTMLInputElement;
    } = {};
    render() {
        return (
            <input
                ref={(input) => this.ctrls.input = input}
                value={this.props.value}
                onChange={(e) => { this.props.onChange(this.ctrls.input.value) } }
                />
        );
    }
    componentDidMount() {
        this.ctrls.input.focus();
    }
}

उन्हें एक वस्तु में रखें


1
कृपया अपना उत्तर स्पष्ट करें
AesSedai101

यह उत्तर ctrls.input को दृढ़ता से टाइप किए गए तत्व पर सेट कर रहा है, जो कि जाने के लिए दृढ़ता से टाइप किया गया तरीका है। यह एक बेहतर "टाइपस्क्रिप्ट" विकल्प है।
डग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.