概要
お世話になります。
現在、Next.js
でアプリケーションを開発していて、その中で要素
をダブルクリック
した場合にdiv
要素、input
要素としてトグル
させるコンポーネント
を作成しています。
フレームワークにNext.js
を利用し、React.js
をTypeScript
形式で記述しています。
トグルさせる手法としてReact Hook
を利用していて、コンポーネント
のトグル状態
、およびエレメント
をuseState
を利用して管理しています。
状態を管理するところまではうまく行ったのですが、トグルさせる処理がうまく行かないので、useState
の挙動等についてご教授頂きたいです。
問題点
まずはソースコードをご覧いただければと思います。
tsx
1import React from 'react' 2import styled, { StyledComponent } from 'styled-components' 3 4export default () => { 5 return ( 6 <Cell 7 text='Hello World!!!' 8 /> 9 ) 10} 11 12const CellStyle: StyledComponent<'div', {}> = styled.div`` 13 14const InputStyle: StyledComponent<'input', {}> = styled.input`` 15 16interface CellInterface { 17 key?: number 18 text: string 19} 20 21const Cell: React.FC<CellInterface> = ({ key = 0, text }) => { 22 const onDoubleClick = () => { 23 if (elementState.selected) { 24 setElementState({ 25 selected: false, 26 element: <CellStyle 27 key={key} 28 onDoubleClick={onDoubleClick} 29 > 30 {text} 31 </CellStyle> 32 }) 33 } else { 34 setElementState({ 35 selected: true, 36 element: <InputStyle 37 key={key} 38 onDoubleClick={onDoubleClick} 39 defaultValue={text} 40 /> 41 }) 42 } 43 } 44 45 type ElementState = { 46 selected: boolean 47 element: JSX.Element 48 } 49 50 const [elementState, setElementState] : [ 51 ElementState, 52 React.Dispatch<React.SetStateAction<ElementState>> 53 ] = React.useState<ElementState>({ 54 selected: false, 55 element: <CellStyle 56 key={key} 57 onDoubleClick={onDoubleClick} 58 > 59 {text} 60 </CellStyle> 61 }) 62 63 return elementState.element 64}
簡単に説明すると、Cell
コンポーネント内でelementState
オブジェクトを管理していて、elementState
はコンポーネントが編集対象として選択されているかを管理するselected
、表示要素であるelement
を保持しています。
CellStyle
、InputStyle
コンポーネントのonDoubleClick
イベントハンドラに関数を登録し、ダブルクリックされた場合、要素の切り替えを行えるようにしています。
上記で問題の箇所はonDoubleClick
です。
僕の期待では、下記の手順を踏むことで処理が行われることを期待しています。
- まず
Cell
コンポーネント内部でuseState
メソッドが呼ばれ、elementState.element
はCellStyle
に設定される。 Cell
コンポーネントをダブルクリックした場合、elementState.selected
はfalse
なので、elementState.selected
はtrue
に設定され、elementState.element
はInputStyle
に設定される。- 再度
Cell
コンポーネントをダブルクリックした場合、elementState.selected
はtrue
なので、elementState.selected
はfalse
に設定され、elementState.element
はCellStyle
に設定される。
しかし僕の手元では上記2
の部分がうまく行っていなく、Cell
コンポーネントをダブルクリックしてもelementState.selected
はtrue
に設定されません。
console.log
等でデバックしていると、上記2
の部分でelementState.element
は期待通りInputStyle
に設定されていますが、elementState.selected
が上手くいきません。
どなたかuseState
の挙動についてご教授頂ければと思います。
上記の説明を文字で見てもわかりづらいと思いますので、下記に再現可能なように環境情報を掲載させて頂きます。
環境情報
項目 | 値 |
---|---|
OS | Windows 10 |
Node | v10.16.2 |
- 構成
sh
1$ find -type f 2./package.json 3./pages/index.tsx
- package.json
json
1{ 2 "name": "tmp", 3 "version": "1.0.0", 4 "description": "", 5 "scripts": { 6 "dev": "next" 7 }, 8 "keywords": [], 9 "author": "", 10 "license": "ISC", 11 "dependencies": { 12 "next": "^9.0.4", 13 "react": "^16.8.6", 14 "react-dom": "^16.8.6", 15 "styled-components": "^4.3.2", 16 "styled-reset": "^3.0.0", 17 "typescript": "^3.5.3" 18 }, 19 "devDependencies": { 20 "@types/next": "^8.0.6", 21 "@types/react": "^16.8.23", 22 "@types/react-dom": "^16.8.5", 23 "@types/styled-components": "^4.1.18", 24 "@zeit/next-typescript": "^1.1.1", 25 "babel-plugin-styled-components": "^1.6.0", 26 "ts-node": "^8.3.0" 27 } 28}
- pages/index.tsx
import React from 'react' import styled, { StyledComponent } from 'styled-components' export default () => { return ( <Cell text='Hello World!!!' /> ) } const CellStyle: StyledComponent<'div', {}> = styled.div`` const InputStyle: StyledComponent<'input', {}> = styled.input`` interface CellInterface { key?: number text: string } const Cell: React.FC<CellInterface> = ({ key = 0, text }) => { const onDoubleClick = () => { if (elementState.selected) { setElementState({ selected: false, element: <CellStyle key={key} onDoubleClick={onDoubleClick} > {text} </CellStyle> }) } else { setElementState({ selected: true, element: <InputStyle key={key} onDoubleClick={onDoubleClick} defaultValue={text} /> }) } } type ElementState = { selected: boolean element: JSX.Element } const [elementState, setElementState] : [ ElementState, React.Dispatch<React.SetStateAction<ElementState>> ] = React.useState<ElementState>({ selected: false, element: <CellStyle key={key} onDoubleClick={onDoubleClick} > {text} </CellStyle> }) return elementState.element }
- 起動コマンド
sh
1$ npm run dev
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。