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

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

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

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

React.js

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

Q&A

解決済

1回答

1399閲覧

Reactでメニュー選択のショートカットを作成

Nero1129

総合スコア130

JavaScript

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

React.js

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

0グッド

0クリップ

投稿2021/06/17 09:04

前提

Reactでメニューの選択をショートカットで行いたいです。
コードは下記のリンクにあります。
ソースコード

実現したいこと

上下キーを押したときに、メニューの選択を切り替えたいです。
下キーを押すと、一つ下の要素を選択して、元の要素の選択を外すみたいなことです。

試したこと

ピュアなJSであれば、適当なInt型の変数を作成し、上下キーを押すと、変数を加減算。
条件式でDOMを切り替えという方法をとると思うのですが、Reactのお作法的にそれはいいのか否やがわからず質問させていただきました。

試したこととしては、共有したコードに別のuseStateを作成

javascript

1const [count, setCount] = useState(0);

これを加減算で条件分岐をしようと思ったのですが、この記事では

フックをループや条件分岐、あるいはネストされた関数内で呼び出してはいけません。

となっていたのと、countが更新されない現象があったので出来ませんでした。
※更新されない理由と、その仕組みは理解しました

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

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

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

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

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

guest

回答1

0

ベストアンサー

となっていたのと、countが更新されない現象があったので出来ませんでした。

おそらくこのようなコードを書いたのではないでしょうか?

js

1const [status, setStatus] = useState(0); 2setStatus(status + 1);

これはおそらく目的には叶わないでしょう。このsetStatus内のstateは初期値(この場合0)から変わらないため、setStatusに与えられる数値は(0 + 1)の値にしかならないでしょう。もし、statusが更新可能であれば、これはconst [status, ...のjavascriptのconstの変数宣言に反するものでも、あるので、この挙動はある意味正しいものと思います。

なので、これは使えません。変わりに使えそうな内容を紹介いたします。

フックの基本的な使い方にありますが、その内容を少し引用します。この内容に関連しそうなのが

関数型の更新

新しい state が前の state に基づいて計算される場合は、setState に関数を渡すことができます。この関数は前回の state の値を受け取り、更新された値を返します。以下は、setState の両方の形式を用いたカウンタコンポーネントの例です。

js

1function Counter({initialCount}) { 2 const [count, setCount] = useState(initialCount); 3 return ( 4 <> 5 Count: {count} 6 <button onClick={() => setCount(initialCount)}>Reset</button> 7 <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> 8 <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button> 9 </> 10 ); 11}

このように、

javascript

1setCount(prevCount => prevCount - 1)

という形で、Reactは、フックに関数を渡すことによって、その関数の引数が更新前の値を表わします。これを利用すれば良いでしょう。具体的には、質問者の書かれたコードの一部ですが、

javascript

1const initState = [true, false, false]; 2 3export default function App() { 4 const [status, setStatus] = useState(initState); 5 6 useHotkeys("up,down,left,right", (e) => { 7 e.preventDefault(); 8 // キーの方向 9 switch (e.key) { 10 case "ArrowUp": 11 break;

これをこのように書き直すと良いでしょう。

javascript

1export default function App() { 2 const [status, setStatus] = useState(0); 3 const menuLastIndex = 2; 4 5 // メニューの選択を次の選択にする 6 function nextMenuItem(prevStatus){ 7 const isNext = prevStatus < menuLastIndex; 8 if(isNext){ 9 return prevStatus + 1; 10 }else{ 11 return prevStatus; 12 } 13 } 14 15 useHotkeys("up,down,left,right", (e) => { 16 e.preventDefault(); 17 // キーの方向 18 switch (e.key) { 19 case "ArrowUp": 20 // 次の選択にすすむ 21 setStatus(nextMenuItem);

これは、メニューの選択をstatusで管理しています。メニューの選択を数値で管理しているため、

javascript

1 <ListItem button divider={true} selected={status[0]}>

を、

javascript

1 <ListItem button divider={true} selected={status == 0}>

のように修正すると良いでしょう。

これらは、コードは全てではなく不完全ではありますが、質問者自身で補完できると思います。もし、分からなければコメントください。問題が解決されることを期待しています。

投稿2021/06/17 12:24

nobkz

総合スコア320

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

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

nobkz

2021/06/18 06:57

はい、一見したとこ、大丈夫だと思います。 それと、「お作法」も大事なのですがあまり気にしすぎるのもよくないかなと思います。Reactの公式のドキュメントで書いてあることを逸脱しないのであればいいんのではないかと。むしろ、ドキュメントに書いてあることをしっかり把握することが大事かなと思いますね。 その上で、コードの可読性や、コンポーネントの責務、疎結合になっているか、宣言的になっているか等を気にすれば良いと思います。 強いていえば、javascriptで、constを多用したり、最新のjsの仕様を把握して、完結に書くことができれば自ずとReactの「お作法」に適うのではないかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問