質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

598閲覧

reactでスクロールに応じてstateを更新したい

uchida_yuma

総合スコア44

Redux

Reduxは、JavaScriptアプリケーションの状態を管理するためのオープンソースライブラリです。ReactやAngularで一般的にユーザーインターフェイスの構築に利用されます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

2クリップ

投稿2020/03/18 05:38

前提・実現したいこと

Reactを使って以下のようにスクロールでstateが更新されるようなロジックを作りたいと思います。

イメージとしては見出しが画面から外れた時に現状の state + 1 で今の番号を定義か、
body内にある見出し要素の中で最も高い位置にある要素を取るかどちらかですが、ロジックが思い付かず質問いたしました。

難しいと感じているのは以下の2つです

  • state更新のタイミング
  • 要素の数が可変であること

イメージ説明

具体的な相談内容

state更新のロジック

jQueryであれば、全ての見出しの同じクラスを振っておき、 body 内にあるもので最も上部にある要素のidで判別すればよいと思いますが、reactの場合 React.createRef() だと同じことができずに困っています。

要素が可変

要素の数は固定ではなく、4〜20の可変なので、stete更新ロジックとも被る問題ですが、各見出し要素の位置を個別に捉えるためのロジックが思い付かず困っています。

ロジックが思い付かず、書いたコードを提示できず申し訳ない質問ですが、もしヒントや何か参考になりそうなリンクがあれば、教えていただけると大変ありがたいです。

どうぞよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

  • react: 16.8
  • 当質問はクラスコンポーネントへの実装を考えております。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

react-event-lisner というパッケージがあります。
この EventListener コンポーネントを使うことで、スクロール時に実行する関数を指定できます。
あとは要素の window からの相対位置を条件として state の更新をすればいいと思います。
要素が可変なので、その通りではないはずですが、簡単な例は以下の通りです。

TypeScript

1const Smaple: React.FC = () => { 2 3 const handleScroll = React.useCallback(() => { 4 const targetElement = document.getElementById('hoge') 5 const y = targetElement?.getBoundingClientRect().top 6 if (y && y > 0) { 7 // setState的な 8 } else { 9 // setState的な 10 } 11 }, []) 12 13 return ( 14 <> 15 <EventListener 16 target="window" 17 onScroll={handleScroll} 18 /> 19 { 20 // 何か id が hoge な要素を持つjsx 21 } 22 </> 23 ) 24}

要素が可変な問題はすでに関数まで落ちているので、map 関数で回す等で解決できるかと思います。
もしわからない部分があれば気軽にコメントください。

投稿2020/03/18 12:09

nerianighthawk

総合スコア544

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uchida_yuma

2020/03/19 04:43

すばらしいご回答をありがとうございました! ご提示のパッケージで以下の関数を呼び出すことで、無事一番トップに近い要素の値をsetState()することができました。 大変助かりまして、感謝申し上げます。 似た問題に当たった方のために書きますと、 document.getElementsByClassName で要素をまとめて取得しましたが、正式な配列ではないので、mapやforEachが使えなかったので、forループで行いました。 ``` handleScroll = (e) => { const targetElements = document.getElementsByClassName('trip-event') let positions = [] // 比較用の配列を作成 for (let i = 0; i < targetElements.length; i++) { if (Math.sign(targetElements[i].getBoundingClientRect().top) === 1) { positions.push({ "key": i, "offset": targetElements[i].getBoundingClientRect().top }) } } this.props.tripStepSuccess(positions.shift().key) } ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問