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

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

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

Routerは、異なるネットワーク同士を相互に接続するための通信機器。インターネットでのデータを自動的に振り分け、一つのインターネット回線を複数のコンピュータで使用することが可能です。DHCPによりIPアドレスを自動的に割振りすることもできます。

React.js

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

Q&A

解決済

1回答

6283閲覧

【React】1文字入力するとフォーカスが外れてしまう(テキストフォーム)

ryota002

総合スコア18

Router

Routerは、異なるネットワーク同士を相互に接続するための通信機器。インターネットでのデータを自動的に振り分け、一つのインターネット回線を複数のコンピュータで使用することが可能です。DHCPによりIPアドレスを自動的に割振りすることもできます。

React.js

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

0グッド

0クリップ

投稿2021/04/20 06:53

編集2021/04/20 07:10

前提・実現したいこと

React(react-router-dom)でtodoリストを作成しています。
タスクの追加のフォームに正常に文字入力ができるようにしたいです。

AddForm.jsxの抜粋(以下に全文記載)

html

1function AddForm(props) { 2 return ( 3 <form onSubmit={props.addTodo}> 4 <input 5 type="text" 6 placeholder="Todoを入力" 7 value={props.inputText} 8 onChange={props.updateInputText} 9 /> 10 <input type="submit" value="追加" /> 11 </form> 12 ); 13}

App.jsxの抜粋

js

1function App() { 2 const [todos, setTodos] = useState( 3 JSON.parse(localStorage.getItem("todos")) || [] 4 ); 5 const [inputText, setInputText] = useState(""); 6 const [editingText, setEditingText] = useState(""); 7 const [filterState, setFilterState] = useState(FILTER_STATE.ALL); 8 9 useEffect(() => { 10 localStorage.setItem("todos", JSON.stringify(todos)); 11 }); 12 13 // 1文字ずつしか入力できなくなった。2021/04/16 14 function updateInputText(e) { 15 setInputText(e.target.value); 16 } 17

発生している問題・エラーメッセージ

react-router を使う前はうまく行っていたのですが、routerを使うとうまくいかなくなりました。
タスク追加のフォームに文字を入力すると1文字ずつしか入力ができません。

該当のソースコード

AddForm.jsx

html

1import "../css/App.css"; 2 3function AddForm(props) { 4 return ( 5 <form onSubmit={props.addTodo}> 6 <input 7 type="text" 8 placeholder="Todoを入力" 9 value={props.inputText} 10 onChange={props.updateInputText} 11 /> 12 <input type="submit" value="追加" /> 13 </form> 14 ); 15} 16 17export default AddForm;

Home.jsx

html

1import "../css/App.css"; 2import React from "react"; 3import AddForm from "./AddForm"; 4import ItemList from "./ItemList"; 5import Footer from "./Footer"; 6 7function Home(props) { 8 return ( 9 <div className="container"> 10 <AddForm 11 addTodo={props.addTodo} 12 inputText={props.inputText} 13 updateInputText={props.updateInputText} 14 /> 15 <ItemList 16 todos={props.todos} 17 toggleCheck={props.toggleCheck} 18 deleteTodo={props.deleteTodo} 19 filterState={props.filterState} 20 /> 21 <Footer 22 changeFilterState={props.changeFilterState} 23 filterState={props.filterState} 24 /> 25 </div> 26 ); 27} 28 29export default Home;

App.jsx

js

1import "../css/App.css"; 2import React, { useState, useEffect } from "react"; 3import { BrowserRouter, Route } from "react-router-dom"; 4import Home from "./Home"; 5import Detail from "./Detail"; 6import Edit from "./Edit"; 7import { FILTER_STATE } from "../const/filter-state"; 8import Header from "./Header"; 9 10function App() { 11 const [todos, setTodos] = useState( 12 JSON.parse(localStorage.getItem("todos")) || [] 13 ); 14 const [inputText, setInputText] = useState(""); 15 const [editingText, setEditingText] = useState(""); 16 const [filterState, setFilterState] = useState(FILTER_STATE.ALL); 17 18 useEffect(() => { 19 localStorage.setItem("todos", JSON.stringify(todos)); 20 }); 21 22 // 1文字ずつしか入力できなくなった。2021/04/16 23 function updateInputText(e) { 24 setInputText(e.target.value); 25 } 26 27 function changeFilterState(e) { 28 setFilterState(e.target.value); 29 } 30 31 function updateEditingText(e) { 32 setEditingText(e.target.value); 33 } 34 35 function addTodo(e) { 36 e.preventDefault(); 37 38 if (inputText.trim() === "") { 39 return; 40 } 41 42 const todosCopy = todos.slice(); 43 todosCopy.push({ 44 createdAt: new Date(), 45 isDone: false, 46 title: inputText, 47 }); 48 49 setTodos(todosCopy); 50 setInputText(""); 51 } 52 function updateTodo(e) { 53 e.preventDefault(); 54 55 if (inputText.trim() === "") { 56 return; 57 } 58 59 const todosCopy = todos.slice(); 60 todosCopy.push({ 61 title: inputText, 62 }); 63 64 setTodos(todosCopy); 65 setEditingText(""); 66 } 67 68 function deleteTodo(targetTodoCreatedAt) { 69 const todosCopy = todos.slice(); 70 71 const newTodos = todosCopy.filter( 72 (todo) => todo.createdAt !== targetTodoCreatedAt 73 ); 74 setTodos(newTodos); 75 } 76 77 function toggleCheck(targetTodoCreatedAt) { 78 const createdAtArray = todos.map((todo) => todo.createdAt); 79 80 const editingTodoIndex = createdAtArray.indexOf(targetTodoCreatedAt); 81 82 const todosCopy = todos.slice(); 83 const checkedState = todosCopy[editingTodoIndex].isDone; 84 85 checkedState 86 ? (todosCopy[editingTodoIndex].isDone = false) 87 : (todosCopy[editingTodoIndex].isDone = true); 88 89 setTodos(todosCopy); 90 } 91 92 return ( 93 <BrowserRouter> 94 <React.Fragment> 95 <Route path="/" component={Header} /> 96 <Route 97 exact 98 path="/" 99 component={() => ( 100 <Home 101 addTodo={addTodo} 102 inputText={inputText} 103 updateInputText={updateInputText} 104 todos={todos} 105 toggleCheck={toggleCheck} 106 deleteTodo={deleteTodo} 107 filterState={filterState} 108 changeFilterState={changeFilterState} 109 /> 110 )} 111 /> 112 <Route 113 exact 114 path="/detail/:id" 115 component={() => <Detail todos={todos} />} 116 /> 117 <Route 118 exact 119 path="/edit/:id" 120 component={() => ( 121 <Edit 122 todos={todos} 123 updateTodo={updateTodo} 124 editingText={editingText} 125 updateEditingText={updateEditingText} 126 /> 127 )} 128 /> 129 </React.Fragment> 130 </BrowserRouter> 131 ); 132} 133 134export default App;

試したこと

react-router-domを使う前のソースコードと見比べましたが、特段変わったところがなく原因がわかりませんでした。

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

json

1 "dependencies": { 2 "@testing-library/jest-dom": "^5.11.4", 3 "@testing-library/react": "^11.1.0", 4 "@testing-library/user-event": "^12.1.10", 5 "react": "^17.0.2", 6 "react-dom": "^17.0.2", 7 "react-router-dom": "^5.2.0", 8 "react-scripts": "4.0.3", 9 "web-vitals": "^1.0.1" 10 },

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

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

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

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

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

guest

回答1

0

ベストアンサー

<Route> の component に渡しているアロー関数が毎回作り直されるため、<Home> も作り直されるのだと思います。component 属性ではなく、普通に <Route> の子要素にすれば良いでしょう。
参考: <Route> (React Router: Declarative Routing for React.js)

js

1 <Route exact path="/"> 2 <Home 3 addTodo={addTodo} 4 inputText={inputText} 5 updateInputText={updateInputText} 6 todos={todos} 7 toggleCheck={toggleCheck} 8 deleteTodo={deleteTodo} 9 filterState={filterState} 10 changeFilterState={changeFilterState} 11 /> 12 </Route>

投稿2021/04/20 09:17

hoshi-takanori

総合スコア7895

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

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

ryota002

2021/04/20 11:11

うまくできました! ありがとうございました!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問