টাইপসক্রিপ্ট সহ প্রতিক্রিয়া মধ্যে কীভাবে রেফ ব্যবহার করবেন


139

আমি প্রতিক্রিয়ার সাথে টাইপস্ক্রিপ্ট ব্যবহার করছি। রেফগুলি কীভাবে ব্যবহার করতে হয় তা বুঝতে আমার সমস্যা হচ্ছে যাতে রেফগুলি দ্বারা রেফারেন্সযুক্ত নোডগুলির সাথে স্থিতিশীল টাইপিং এবং ইন্টেলিসেন্স পাওয়া যায়। আমার কোডটি নিম্নরূপ।

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

আপনি যদি 16.3+ প্রতিক্রিয়া ব্যবহার করেন তবে রেফ তৈরির জন্য প্রস্তাবিত উপায়টি ব্যবহার করা হচ্ছে 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সম্পত্তি রেফারেন্সকৃত উপাদান / nullডিওএম উপাদানকে অর্পণ করা হবে এবং যখন এটি আনমসেট করা হবে তখন এটিকে পুনরায় বরাদ্দ করা হবে। সুতরাং, উদাহরণস্বরূপ, আপনি এটি ব্যবহার করে অ্যাক্সেস করতে পারেনthis.stepInput.current

আরো জানার জন্য RefObjectদেখুন @ apieceofbart এর উত্তর বা জনসংযোগ createRef() মধ্যে যোগ করা হয়েছিল।


যদি আপনি প্রতিক্রিয়াটির পূর্ববর্তী সংস্করণ ব্যবহার করেন (<16.3) বা রেফগুলি সেট এবং সেট না করা হয় তখন আরও সূক্ষ্ম নিয়ন্ত্রণের প্রয়োজন হয়, আপনি "কলব্যাক রেফ" ব্যবহার করতে পারেন ।

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} />
    }
}

উপাদানটি মাউন্ট করলে, প্রতিক্রিয়াটি ডিওএম refউপাদানটির সাথে কলব্যাক কল করবে এবং nullযখন এটি আনমসেট হবে তখন এটিকে কল করবে । সুতরাং, উদাহরণস্বরূপ, আপনি কেবল এটি ব্যবহার করে অ্যাক্সেস করতে পারেন this.stepInput

refএকটি ইনলাইন ফাংশন ( এই উত্তরের আগের সংস্করণ হিসাবে) এর বিপরীতে ক্লাসে একটি আবদ্ধ পদ্ধতি হিসাবে কলব্যাককে সংজ্ঞায়িত করে আপনি আপডেটের সময় কলব্যাক দু'বার কল করা এড়াতে পারবেন ।


সেখানে ব্যবহার করা হয় একটি API যেখানে ref(দেখুন অ্যাট্রিবিউট একটি স্ট্রিং ছিল অক্ষর প্যাটেল এর উত্তর ), কিন্তু কারণে কিছু সমস্যা , স্ট্রিং refs জোরালোভাবে নিরুৎসাহিত হয়ে এবং শেষ পর্যন্ত মুছে ফেলা হবে।


প্রতিক্রিয়া 16.3 এর নতুন পদ্ধতিতে যুক্ত করার জন্য 22 মে, 2018 সম্পাদিত। একটি নতুন উপায় আছে তা দেখানোর জন্য @ পেপিসোফবার্টকে ধন্যবাদ জানাই।


এই পছন্দ উপায় লক্ষ্য করুন। refsশ্রেণীর বৈশিষ্ট্য সহ নীচের উদাহরণগুলি আসন্ন প্রতিক্রিয়া সংস্করণগুলিতে হ্রাস করা হবে।
জিমি পাজালা

1
দয়া করে মনে রাখবেন যে এটি ইতিমধ্যে একটি পুরানো উপায় :) বর্তমান হ'ল React.createRef () ব্যবহার করা হয়
apieceofbart

@ অ্যাপিসোফবার্ট মাথা উঁচু করার জন্য ধন্যবাদ। নতুন উপায় অন্তর্ভুক্ত করার জন্য উত্তর আপডেট করেছেন Updated
জেফ বোয়েন

2
আমি আপনার উত্তরে
টাইপসক্রিপ্ট

উপস। আমার মূল উত্তরে টাইপসক্রিপ্ট ছিল তবে এটি নতুনটিতে অন্তর্ভুক্ত করতে ভুলে গিয়েছি। এটিকে আবার যুক্ত করা হয়েছে এবং পাশাপাশি আপনার উত্তরের সাথে সংযুক্ত করা হয়েছে। ধন্যবাদ।
জেফ বোয়েন

30

একটি উপায় (যা আমি করছি ) হ'ল ম্যানুয়ালি সেটআপ করা:

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

তারপরে আপনি এটিকে একটি ভাল গিটার ফাংশনেও গুটিয়ে রাখতে পারেন (যেমন: এখানে ):

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

1
ধন্যবাদ @ বাসারত আমি আপনার সমাধানটি চেষ্টা করেছি তবে আমি এই ত্রুটিটি পেয়েছি 'টাইপ এলিমেন্টটি এইচটিএমএল ইনপুট এলিমেন্ট টাইপ করার যোগ্য নয়। সম্পত্তির গ্রহণযোগ্য উপাদান এলিমেন্টে 'অনুপস্থিত'
অক্ষর প্যাটেল

প্রতিক্রিয়া-ডোম সংজ্ঞাগুলির নতুন সংস্করণে কোনও সমস্যা হতে পারে। ইতিমধ্যে
দৃser়তা

স্পষ্টতই anyএখানে বাধ্যতামূলক নয়। বেশিরভাগ উদাহরণ আমি ব্যবহার দেখতে পাচ্ছি HTMLInputElement। কেবল সুস্পষ্টভাবে উল্লেখ করে, তবে যদি আপনার রেফ একটি প্রতিক্রিয়া উপাদানটিতে থাকে (যেমন PeoplePicker), আপনি টাইপগুলি পাওয়ার জন্য সেই উপাদানটি টাইপ হিসাবে ব্যবহার করতে পারেন।
জো মার্টেলা

23

যেহেতু 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);
}

সঠিক দিকে নির্দেশ করার জন্য @ বাসারতকে ধন্যবাদ।


2
Property 'stepInput' does not exist on type '{ [key: string]: Component<any, any> | Element; }'অ্যাক্সেস করার চেষ্টা করার সময় আমি এখনও পাচ্ছি this.refs.stepInput
নিক সুমেকো

@ নিকসুমাইকো, আপনি যে ত্রুটিটি পেয়েছিলেন কারণ আপনার refsবস্তুটিতে কেবল [key: string]প্রবেশ ছিল ।
জো মার্টেলা

9

React.createRef (বর্গ উপাদান)

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

দ্রষ্টব্য: পুরাতন স্ট্রিং রেফস উত্তরাধিকার 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
}

নোট: কি শুরু করা 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প্রকার তৈরি করে । প্রাক্তনটি ব্যবহার করা যেতে পারে, যদি আপনাকে নিজের রেফগুলিতে বর্তমান ডিওএম নোডগুলি পরিবর্তন করতে হয়, যেমন বাহ্যিক লাইব্রেরির সাথে মিশ্রণ। এছাড়া ছাড়া লেখা যেতে পারে : । বেশিরভাগ ক্ষেত্রে ব্যবহৃত প্রতিক্রিয়াযুক্ত ডোম নোডগুলির জন্য উত্তরটি আরও ভাল পছন্দ for প্রতিক্রিয়াগুলি নিজেই নোডগুলিকে রেফগুলিতে সঞ্চয় করে এবং আপনি এই মানগুলি পরিবর্তনের সাথে লুটিয়ে পড়তে চান না। currentreadonlyasuseRef<HTMLInputElement | null>(null)
ford04

1
স্পষ্টতার জন্য ধন্যবাদ।
ksav

7

আপনি যদি ব্যবহার করছেন React.FCতবে HTMLDivElementইন্টারফেসটি যুক্ত করুন :

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

এবং এটি নীচের মত ব্যবহার করুন:

return <div ref={myRef} />;

1
ধন্যবাদ। এই জুড়ে যে কেউ আসে তার জন্য আরেকটি টিপ হল এলিমেন্টটি পরীক্ষা করা। এই উদাহরণটি একটি ডিআইভি উপাদান ব্যবহার বোঝায়। উদাহরণস্বরূপ একটি ফর্ম ব্যবহার করবে - 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/ স্টংগ্রি-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']);

রেফস সূচকটির নতুন সংজ্ঞা ছাড়াই।

@ মানাকোর যেমন উল্লেখ করেছেন আপনি তেমনি ত্রুটি পেতে পারেন

'Step [কী: স্ট্রিং]: উপাদান | টাইপ করে সম্পত্তি' স্টেপ ইনপুট 'বিদ্যমান নেই উপাদান; }

আপনি যদি পুনরায় সংজ্ঞা দেন (আপনি যে আইডিই এবং টিএস সংস্করণ ব্যবহার করেন তার উপর নির্ভর করে)


0

কেবল একটি পৃথক পদ্ধতির যোগ করতে - আপনি কেবল আপনার রেফকে কাস্ট করতে পারেন, এরকম কিছু:

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

0

আমি সর্বদা এটি করি, সেক্ষেত্রে একটি রেফ নিতে

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


ইনপুট যাক: এইচটিএমএলপুটইমেন্ট = রিঅ্যাক্টডোম.ফাইন্ডডমনোড <এইচটিএমএল ইনপুট উপাদান> (এটি.আরফস ['ইনপুট']);
ব্যবহারকারী2662112

0

refপ্রপস ইন্টারফেসে আপনি যদি আপনার ফরোয়ার্ড করতে না চান তবে আপনার 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

এই উত্তরটি দৃtr়ভাবে টাইপ করা উপাদানগুলিতে ctrls.input সেট করছে, যা যাওয়ার জন্য দৃ strongly়ভাবে টাইপ করা উপায়। এটি একটি ভাল "টাইপস্ক্রিপ্ট" পছন্দ is
ডগ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.