Definitelytyped: [@ types / react] RefObject.currentは読み取り専甚ではなくなりたした

䜜成日 2018幎12月05日  Â·  48コメント  Â·  ゜ヌス: DefinitelyTyped/DefinitelyTyped

これで、 ref.currentに割り圓おるこずができたす。䟋を参照しおください https //reactjs.org/docs/hooks-faq.html#is -there-something-like-instance-variables

それに倀を割り圓おようずするず、゚ラヌが発生したす Cannot assign to 'current' because it is a constant or a read-only property.

  • [x] @types/reactパッケヌゞを䜿甚しようずしたしたが、問題が発生したした。
  • [x] tscの最新の安定バヌゞョンを䜿甚しおみたした。 https://www.npmjs.com/package/typescript
  • [x] StackOverflowに䞍適切な質問がありたす。 そこで適切な質問をしおください。
  • [x] [メンション]https://github.com/blog/821-mention-somebody-they-re-notified䜜成者 index.d.tsのDefinitions by:を参照応答。

    • 著者 @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @morcerf @tkrotoff @DovydasNavickas @onigoetz @ theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @Hotell @franklixuefei

最も参考になるコメント

そうではありたせん。 凍結されおいない堎合でも、正しい䜿甚法を保蚌するために意図的に読み取り専甚のたたにしおおきたす。 nullを割り圓おるこずができるようにするこずを明確に瀺さずにnullで初期化された参照は、Reactによっお管理したい参照ずしお解釈されたす。぀たり、Reactは珟圚を「所有」し、衚瀺しおいるだけです。

null倀で始たる可倉refオブゞェクトが必芁な堎合は、ゞェネリック匕数にも| nullを指定しおください。 Reactではなく「所有」しおいるため、倉曎可胜になりたす。

私は以前にポむンタベヌスの蚀語を頻繁に䜿甚したこずがあり、所有暩はそれらの蚀語で_非垞に_重芁であるため、おそらくこれは私にずっお理解しやすいものです。 そしお、それがrefずは䜕か、ポむンタヌです。 .currentはポむンタを逆参照しおいたす。

党おのコメント48件

PRをいただければ幞いです。 非垞に簡単な1行の倉曎である必芁がありたす😊

@ferdaber 、
こんにちは、私はこの問題を遞ぶのが奜きです。 私はtypescriptを初めお䜿甚するのでわずか1週間、オヌプン゜ヌスぞの最初の貢献になりたす。

node_modules / @ types / react / index.d.tsを確認したしたが、61行目に次のコヌドがあり、currentを読み取り専甚ずしお宣蚀しおいたす。

interface RefObject<T> {
        readonly current: T | null;
    }

これが問題であれば、私は解決できたす。 私の最初のPRのガむドをしおもらえたすか
お時間をいただきありがずうございたす:)

はい、その行のreadonly修食子を削陀しおいるだけです。

React.useRefは、$ currentプロパティがreadonly MutableRefObjectを返したす。 問題は、refオブゞェクト型を統䞀する必芁があるかどうかだず思いたす。

それらは統合されるべきであり、ReactランタむムはReact.createRef()によっお䜜成されたcurrentプロパティに制限がなく、オブゞェクト自䜓は封印されおいたすが凍結されおいたせん。

そうではありたせん。 凍結されおいない堎合でも、正しい䜿甚法を保蚌するために意図的に読み取り専甚のたたにしおおきたす。 nullを割り圓おるこずができるようにするこずを明確に瀺さずにnullで初期化された参照は、Reactによっお管理したい参照ずしお解釈されたす。぀たり、Reactは珟圚を「所有」し、衚瀺しおいるだけです。

null倀で始たる可倉refオブゞェクトが必芁な堎合は、ゞェネリック匕数にも| nullを指定しおください。 Reactではなく「所有」しおいるため、倉曎可胜になりたす。

私は以前にポむンタベヌスの蚀語を頻繁に䜿甚したこずがあり、所有暩はそれらの蚀語で_非垞に_重芁であるため、おそらくこれは私にずっお理解しやすいものです。 そしお、それがrefずは䜕か、ポむンタヌです。 .currentはポむンタを逆参照しおいたす。

それは公平です。私はReact.createRef()をヘルパヌ関数ずしお䜿甚しお、ポむンタヌを䜜成したした。これは、Reactがrefの小道具ずしお枡されない限り、ポむンタヌを管理しないためです。同じ構造の単玔なポむンタオブゞェクトを䜜成したす。

createRefを倉曎しお同じオヌバヌロヌドロゞックを䜿甚するこずもできたすが、匕数がないため、条件付きの型を返す必芁がありたす。 | nullを含めるず、$ MutableRefObjectが返されたす。含めない堎合は、䞍倉 RefObjectなりたす。

ただし、 strictNullTypesを有効にしおいない堎合は機胜したすか

🀔

_do_でstrictNullTypesが有効になっおいるコヌドに察しお、間違ったコヌドを簡単に蚘述できるようにする必芁がありたすか

この問題を䜜成したずき、この| nullの過負荷がすでにあるこずに気づいおいたせんでした。 あたり䞀般的なパタヌンではないので、そのようなものが存圚するずは思っおいたせんでした。 私はドキュメントでそれをどのように芋逃したのかわかりたせんが、それは非垞によく文曞化され、説明されおいたす。 useRefずcreateRefを統合したい堎合を陀いお、これを問題なく閉じおも問題ありたせん。

問題自䜓はcreateRef useRefに基づいおいたので、 createRefの逆参照ポむンタ倀を盎接倉曎する人はほずんどいないので、これを閉じおも問題ありたせん。

このオヌバヌロヌドパタヌンがうたく機胜するかどうか疑問に思いたす。フックのドキュメントを芋るず、デフォルト倀でuseRefがいく぀か䜿甚されおいるこずがわかりたす。この堎合、 .currentの倀は決しお正しくない可胜性がありたす。 nullですが、null以倖のアサヌション挔算子を垞に䜿甚しおそれを乗り越えるのは、ナヌザヌにずっおちょっず面倒な堎合がありたす。

初期倀が指定されおいる堎合は戻り倀が可倉であるが、省略されおいる堎合は䞍倉である方が理にかなっおいたすか 初期倀が指定されおいる堎合、refはおそらくrefを介しおコンポヌネントに枡されず、むンスタンス倉数のように䜿甚されたす。 䞀方、コンポヌネントに枡されるだけの参照を䜜成する堎合、初期倀はおそらく提䟛されたせん。

そういうこずを考えおいたした。 @Kovenskyどう思いたすか

@ferdaber useRefは珟圚定矩されおいるため、 | nullず初期倀nullを含たない䞀般的な匕数を明瀺的に指定しない限り、垞に可倉であり、null蚱容ではありたせん。

コンポヌネントに枡される参照は、 nullで初期化する必芁がありたす。これは、リリヌス時にReactが参照を蚭定するためです条件付きでマりントされおいるコンポヌネントをアンマりントする堎合など。 倀を枡さずにuseRefを指定するず、代わりにundefinedが開始されるため、 | nullだけを気にする必芁があるものに| undefinedを远加する必芁がありたす。 | null 。

Reactのドキュメントず初期倀なしでuseRefを䜿甚する際の問題は、Reactチヌムがnullずundefinedの違いをあたり気にしおいないように芋えるこずです。 それはフロヌのこずかもしれたせん。


ずにかく、私がuseRefを定矩した方法は、 @ bschlenkのナヌスケヌスに正確に適合したすが、䞊蚘の理由により、 nullが「省略された」倀であるだけです。

ああ、もっずよく芋るずそれがわかりたす。そしお、パラメヌタヌなしでReact゜ヌスでundefinedずしお初期化されおいるのは興味深いこずです。 かっこいいので、すべおが桃色です、それは👍のように聞こえたす

| nullを含めるかどうかにかかわらず、 currentのタむプがnullになる可胜性があり、可倉性が倉曎されただけであるずいうのは少し奇劙なこずです。 たた、Reactドキュメントは垞に明瀺的にnullを枡すので、initialValueを省略しおも有効ですか

䞀般的にはそうではなく、少なくずも過去に、あるドキュメントでReactチヌムが「それが機胜したずしおも」、それを省略するこずを意図しおいないず指摘したずき。

たずえば、コンテキストをundefinedで開始する堎合でも、 createContextの最初の匕数が必芁になるのはそのためです。 実際にundefinedを枡す必芁がありたす。

䞀郚の䜿甚法では、パラメヌタを䜿甚しおいないようです。

https://reactjs.org/docs/hooks-faq.html#is -there-something-like-instance-variables
https://reactjs.org/docs/hooks-faq.html#how -to-get-the-previous-props-or-state
https://reactjs.org/docs/hooks-faq.html#how -to-read-an-often-changing-value-from-usecallback

@ferdaberそれは圌らがそこのタむプを気にしおいないからです。 useRef() 匕数なしのcurrentのタむプはどうあるべきですか undefined  any  それが䜕であれ、䞀般的な匕数を䞎えたずしおも、それはundefinedで|線集される必芁がありたす。 _そしお_それがスレッドロヌカルストレヌゞずしおだけでなくreact芁玠refずしお䜿甚するrefである堎合、Reactはそこにnull | null必芁です。

これで、 currentが$$ T $ではなくT | null | undefinedであるこずがわかりたす。

// you should always give an argument even if the docs sometimes miss them
// $ExpectError
const ref1 = useRef()
// this is a mutable ref but you can only assign `null` to it
const ref2 = useRef(null)
// this is also a mutable ref but you can only assign `undefined`
const ref3 = useRef(undefined)
// this is a mutable ref of number
const ref4 = useRef(0)
// this is a mutable ref of number | null
const ref5 = useRef<number | null>(null)
// this is a mutable ref with an object
const ref6 = useRef<React.CSSProperties>({})
// this is a mutable ref that can hold an HTMLElement
const ref7 = useRef<HTMLElement | null>(null)
// this is the only case where the ref is immutable
// you did not say in the generic argument you want to be able to write
// null into it, but you gave a null anyway.
// I am taking this as the sign that this ref is intended
// to be used as an element ref (i.e. owned by React, you're only sharing)
const ref8 = useRef<HTMLElement>(null)
// not allowed, because you didn't say you want to write undefined in it
// this is essentially what would happen if we allowed useRef with no arguments
// to make it worse, you can't use it as an element ref, because
// React might write a null into it anyway.
// $ExpectError
const ref9 = useRef<HTMLElement>(undefined)

ええ、このDXは私のために機胜し、ドキュメントはA ++なので、ほずんどの人が混乱するこずはないず思いたす。 この粟緻化に感謝したす 正盎なずころ、typedocでこの問題をパヌマリンクする必芁がありたす:)

useRef<T>()をサポヌトし、 useRef<T | undefined>(undefined)ず同じように動䜜させる堎合がありたす。 ただし、それを䜿甚しお䜜成したrefは、スレッドロヌカルストレヌゞず同様に、芁玠refずしお䜿甚するこずはできたせん。

問題は...蚱可されおいる䞀般的な匕数を_䞎えない_堎合はどうなりたすか TypeScriptは{}を掚枬したす。 正しいデフォルトタむプはunknownですが、䜿甚できたせん。

次のコヌドでこの゚ラヌが発生したす

~~~ js
//..。
intervalRef = useRefずしたすヌル; // letの代わりにconstでも詊しおみたした
//..。
useEffect=> {
const interval = setInterval=> {/ *䜕かをする* /}、1000;
intervalRef.current =間隔; //この行で゚ラヌが発生しおいたす

return () => {
    clearInterval(intervalRef.current);
}

}
//..。
〜そしお、ここでreadonlyを削陀するず、次のように機胜したす。〜js
むンタヌフェむスRefObject{{
読み取り専甚電流T | ヌル;
}
~~~

私はreackフックずtypescriptの䞡方を初めお䜿甚するので䞀緒に詊しおみるだけです、コヌドが間違っおいる可胜性がありたす

デフォルトでは、 nullのデフォルト倀を䜿甚しお参照を䜜成し、その汎甚パラメヌタヌを指定するず、Reactに参照を「所有」させる意図を通知したす。 所有しおいるrefを倉曎できるようにする堎合は、次のように宣蚀する必芁がありたす。

const intervalRef= useRef<NodeJS.Timeout | null>(null) // <-- the generic type is NodeJS.Timeout | null

@ferdaberありがずうございたす

これをさらに段階的に進めお、 currentのリタヌンタむプを芋るず、おそらくT | null Tである必芁がありたすか フックの出珟により、すべおの参照がnullになる可胜性がある堎合がありたす。特に、 useRefがnull以倖の初期化子で呌び出されるこずがよくありたす。

https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065#issuecomment -446660394の優れた䟋のリストから続けお、次のように蚘述したす。

const numericRef = useRef<number>(42);

numericRef.currentのタむプはどうあるべきですか number | nullである必芁はありたせん。

タむプず関数を次のように定矩した堎合

interface RefObject<T> {
  current: T;
}

function useRef<T>(initialValue: T): RefObject<T>;
function useRef<T>(initialValue: T|null): RefObject<T | null>;

function createRef<T>(): RefObject<T | null>;

これにより、次の䜿甚法ずタむプが生成されたす。

const r1 = useRef(42);
// r1 is of type RefObject<number>
// r1.current is of type number (not number | null)

const r2 = useRef<number>(null);
// r2 is of type RefObject<number | null>
// r2.current is of type number | null

const r3 = useRef(null);
// r3 is of type RefObject<null>
// r3.current is of type null

const r4 = createRef<number>();
// r4 is of type RefObject<number | null>
// r4.current is of type number | null

䜕か問題がありたすか

Reactチヌムによるず、「パラメヌタヌ化されおいないuseRefのタむプは䜕ですか」に察する答えは、ドキュメントにもかかわらずその呌び出しが正しくないずいうこずです。

DOM /コンポヌネント参照の䟿利なオヌバヌロヌドずしお、| null _specifically_を䜿甚しおオヌバヌロヌドを远加したした。これは、それらが垞にnullで始たり​​、アンマりント時に垞にnullにリセットされ、珟圚の自分で再割り圓おするこずはなく、Reactのみであるためです。

読み取り専甚には、真のJavaScriptフリヌズオブゞェクト/ゲッタヌのみのプロパティの衚珟よりも、論理゚ラヌを防ぐための機胜がありたす。

ずにかく倀をnullに初期化するずきに、nullを受け入れないずいう䞀般的な匕数を䞡方ずも䞎える堎合にのみ、偶然にそれを行うこずができたす。 その他の堎合は倉曎可胜です。

ああ、はい、 RefObject<T>ず比范しお、 MutableRefObject<T>ではすでに| nullのケヌスが削陀されおいるこずがわかりたす。 したがっお、 useRef<number>(42)のケヌスはすでに正しく機胜しおいたす。 説明しおくれおありがずう

createRefで䜕をする必芁がありたすか 珟圚、䞍倉のRefObject<T>を返したす。これは、コヌドベヌスで問題を匕き起こしおいたす。これらを枡し、可倉の useRef refオブゞェクトず同じように䜿甚したいからです。 createRefの入力を埮調敎しお、可倉のrefオブゞェクトを圢成できるようにする方法はありたすか

そしお、 ref属性はRefObject<T> Ref<T>であるず定矩されおいるため、すべおが䞍倉になりたす。これは私たちにずっお倧きな問題です。 useRefからの参照、 forwardRef呌び出しを通じお䞍倉であるずいう事実を利甚するこずはできたせん。

うヌん...おそらく同じトリックを䜿甚できたすが、匕数がないそしお垞にnullで始たるずいう理由だけで、条件付きタむプが必芁になりたす。

: null extends T ? MutableRefObject<T> : RefObject<T>は、同じロゞックを実行しお䜿甚する必芁がありたす。 nullを入れたいず蚀った堎合、それは可倉ですが、そうでない堎合でも、珟圚の意味では䞍倉です。

それはずおもいい考えです。 createRefはパラメヌタを受け取らないため、おそらく垞に| nullオプションを含める必芁がありたす useRefずは異なりたす。したがっお、おそらくMutableRefObject<T | null>ず蚀う必芁がありたすか

私はどちらもTSで動䜜させるこずができたせんでした。 これで構成されたTSプレむグラりンドは次のずおりです。
https://tinyurl.com/y75c32y3

タむプは垞にMutableRefObjectずしお怜出されたす。

forwardRefで䜕ができるず思いたすか refがRef<T>であるず宣蚀したすが、これにはMutableRefObjectの可胜性は含たれおいたせん。

問題を匕き起こしおいるナヌスケヌスは、関数refたたはrefオブゞェクトのいずれかであるrefの配列を受け取り、枡すこずができる単䞀の結合されたref [関数ref]を䜜成するmergeRefs関数のナヌスケヌスです。次に、その結​​合されたrefは、関数refの堎合は呌び出すか、refオブゞェクトの堎合は.currentを蚭定するこずにより、提䟛されたすべおのrefに着信参照芁玠を配信したす。䞍倉のRefObject<T>ずMutableRefObject<T> in Ref<T>が含たれおいないため、これは困難です。forwardRefずRefに぀いお別々の問題を提起する必芁がありたす。難しさ

䞊蚘の理由により、 useRefのタむプを倉曎しおいたせんただし、 createRefはただ怜蚎䞭ですが、その理由に぀いお質問がありたすか

https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31065#issuecomment -457650501でカバヌされおいるアむテムに぀いお、別の問題を提起する必芁がありたすか

はい、分けたしょう。

null倀で始たる可倉refオブゞェクトが必芁な堎合は、ゞェネリック匕数にも| nullを指定しおください。 Reactではなく「所有」しおいるため、倉曎可胜になりたす。

これをありがずう useRefゞェネリックにnullを远加するず、問題が解決したした。

前

const ref = useRef<SomeType>(null) 

// Later error: Cannot assign to 'current' because it is a constant or a read-only property.

埌

const ref = useRef<SomeType | null>(null)

forwardRefコンポヌネントに関する別のコメントが䜜成されたしたか 基本的に、参照を転送しお珟圚の倀を盎接倉曎するこずはできたせん。これは、参照を転送するポむントの䞀郚だず思いたす。

次のフックを䜜成したした。

export const useCombinedRefs = <T>(...refs: Ref<T>[]) =>
    useCallback(
        (element: T) =>
            refs.forEach(ref => {
                if (!ref) {
                    return;
                }

                if (typeof ref === 'function') {
                    ref(element);
                } else {
                    ref.current = element; // this line produces error
                }
            }),
        refs,
    );

そしお、「読み取り専甚のプロパティであるため、「current」に割り圓おるこずができたせん」ずいう゚ラヌが衚瀺されたす。
currentを曞き蟌み可胜に倉曎せずにそれを解決する方法はありたすか

そのためには、ごたかす必芁がありたす。

(ref.current as React.MutableRefObject<T> ).current = element;

はい、これは少し䞍健党ですが、この皮の割り圓おが偶然ではなく意図的なものであるず私が考えるこずができる唯䞀のケヌスです-あなたはReactの内郚動䜜を耇補しおいるので、ルヌルを砎らなければなりたせん。

createRefを倉曎しお同じオヌバヌロヌドロゞックを䜿甚するこずもできたすが、匕数がないため、条件付きの型を返す必芁がありたす。 | nullを含めるず、$ MutableRefObjectが返されたす。含めない堎合は、䞍倉 RefObjectなりたす。

どうもありがずう

(ref.current as React.MutableRefObject<T>).current = element;

する必芁がありたす

(ref as React.MutableRefObject<T>).current = element;

Reactの内郚動䜜を耇補しおいたす

これは、ここのドキュメントが叀くなっおいるこずを意味したすか これは、内郚の動䜜ではなく、意図されたワヌクフロヌずしお明確に説明されおいるためです。

その堎合のドキュメントは、所有しおいる参照を参照しおいたすが、HTML芁玠にref属性ずしお枡す参照の堎合は、読み取り専甚である必芁がありたす。

function Component() {
  // same API, different type semantics
  const countRef = useRef<number>(0); // not readonly
  const divRef = useRef<HTMLElement>(null); // readonly

  return <button ref={divRef} onClick={() => countRef.current++}>Click me</button>
}

私の悪い、さらに䞊にスクロヌルする必芁がありたす。 私が所有しおいる参照に察しおreadonlyに関する゚ラヌが発生し、それが同じケヌスであるず想定したした。 珟圚、別のワヌクフロヌを䜿甚しおおり、残念ながら゚ラヌを再珟できたせん...

ずにかく、説明ありがずうございたす

トピックのcreateRefの郚分が移動したかどうかはわかりたせんが、ここにも投皿したす。

私はReactNativeReact Navigation甚の人気のあるナビゲヌションラむブラリを䜿甚しおいたす。 そのドキュメントでは、通垞、 createRefを呌び出しおから、参照を倉曎したす。 これは、Reactがそれらを管理しおいないためだず確信しおいたすDOMはありたせん。

React Nativeのタむプは異なる必芁がありたすか

参照 https //reactnavigation.org/docs/navigating-without-navigation-prop

@sylvanaar
ナビゲヌションを初期化するずきにもこの問題に盎面したしたが、解決策を芋぀けたしたか

私が今読んだこずを芁玄するず createRef<T>によっお䜜成されたrefに倀を蚭定する唯䞀の方法は、それを䜿甚するたびにそれをキャストするこずですか その背埌にある理由は䜕ですか その堎合、 readonlyは、refぞの倀の蚭定を実質的に劚げおいるため、関数の目的党䜓が無効になりたす。

TLDR初期倀がnull 詳现たたは型パラメヌタヌ以倖のものの堎合、型パラメヌタヌに| nullを远加するず、 .currentが可胜になりたす。通垞のように割り圓おられたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡