🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

React.js

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

Q&A

1回答

4641閲覧

Reactで編集機能を作りたい

NY9

総合スコア5

JavaScript

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

React.js

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

0グッド

1クリップ

投稿2019/10/03 14:35

編集2019/10/04 05:45

Reactで編集機能を作りたいです。
this.stateにediting=falseを設定して、クリックするとediting=trueに切り替わりselect,inputにクリックした内容が表示されるという動きにしたいのですがどうしたらよいでしょうか。

Javascript

1import React from 'react'; 2import Loop from './Loop'; 3import './list.css' 4import EditForm from './EditForm' 5 6const fixed= ["月曜日","火曜日","水曜日","木曜日","金曜日"] 7 8class App extends React.Component{ 9 constructor(props) { 10 super(props); 11 this.state = { 12 lists:[], 13 input:"", 14 value:"", 15 days:"", 16 editing:false 17 } 18 this.handleChange = this.handleChange.bind(this); 19 this.handleSubmit = this.handleSubmit.bind(this); 20 this.handleChangeDays = this.handleChangeDays.bind(this); 21 this.handleDelete = this.handleDelete.bind(this); 22 this.handleChangeEditing = this.handleChangeEditing.bind(this); 23 } 24 25 render () { 26 const {editing}=this.state 27 return ( 28 <div> 29 <h1>時間割</h1> 30 <form> 31 <select 32 defaultValue="---" 33 value={this.state.days} 34 onChange={this.handleChangeDays}> 35 <option>---</option> 36 <option value="月曜日">月曜日</option> 37 <option value="火曜日">火曜日</option> 38 <option value="水曜日">水曜日</option> 39 <option value="木曜日">木曜日</option> 40 <option value="金曜日">金曜日</option> 41 </select> 42 43 <select 44 defaultValue="---" 45 value={this.state.value} 46 onChange={this.handleChangeOrders}> 47 <option>---</option> 48 <option value="1限:">1限</option> 49 <option value="2限:">2限</option> 50 <option value="3限:">3限</option> 51 <option value="4限:">4限</option> 52 <option value="5限:">5限</option> 53 </select> 54 55 {editing ? ( 56 <EditForm 57 text={this.state.input}/> 58 ):( 59 <div> 60 <input 61 onChange={this.handleChange} 62 type="text" 63 value={this.state.input} 64 /> 65 66 <button onClick={this.handleSubmit}>保存</button> 67 <button onClick={this.handleDelete}>削除</button> 68 </div> 69 )} 70 </form> 71 72 73 <div className="p-list"> 74 {fixed.map((l) =>( 75 <div className="list" key={l.toString()}> 76 <p>{l}</p> 77 <p> 78 <Loop 79 onClick={this.handleChangeEditing} 80 lists={this.state.lists.filter(item => item.days === l)} 81 /> 82 </p> 83 </div> 84 ))} 85 </div> 86 87 </div> 88 ); 89 } 90 91 handleChangeEditing () { 92 this.setState({ 93 editing: !this.state.editing 94 }) 95 } 96 97 handleDelete () { 98 this.setState({ 99 input: this.state.input, 100 value: this.state.value, 101 days: this.state.days}) 102 } 103 104 handleChange = (event) => { 105 this.setState({input:event.target.value}) 106 } 107 handleChangeDays = (event) => { 108 this.setState({days:event.target.value}) 109 } 110 handleChangeOrders = (event) => { 111 this.setState({value:event.target.value}) 112 } 113 114 handleSubmit (e) { 115 e.preventDefault(); 116 if (!this.state.input) return; 117 this.setState( 118 { 119 lists: [ 120 ...this.state.lists, 121 { 122 input: this.state.input, 123 value: this.state.value, 124 days: this.state.days 125 }], 126 input:"", 127 days:"", 128 value:"" 129 }); 130 }; 131 132} 133 134export default App;

Javascript

1import React from 'react'; 2 3class Loop extends React.Component { 4 render () { 5 return ( 6 <div> 7 {this.props.lists.map((l) =>( 8 <div key={l.days}> 9 <div onClick={this.props.onClick}>{l.value}{l.input}</div> 10 </div> 11 ))} 12 </div> 13 ); 14 } 15 16} 17 18export default Loop;

Javascript

1import React from 'react'; 2 3class EditForm extends React.Component { 4 constructor (props) { 5 super(props); 6 this.state = { 7 text: props.text 8 }; 9 10 this.handleChange = this.handleChange.bind(this); 11 this.handleSubmit = this.handleSubmit.bind(this); 12 this.handleChangeDays = this.handleChangeDays.bind(this); 13 this.handleDelete = this.handleDelete.bind(this); 14 this.handleChangeEditing = this.handleChangeEditing.bind(this); 15 } 16 render(){ 17 return ( 18 <div> 19 <input 20 onChange={this.handleChange} 21 type="text" 22 value={this.state.text} 23 /> 24 25 <button onClick={this.handleSubmit}>保存</button> 26 <button onClick={this.handleDelete}>削除</button> 27 </div> 28 ); 29 } 30 31 handleDelete () { 32 this.setState({ 33 input: this.state.input, 34 value: this.state.value, 35 days: this.state.days}) 36 } 37 38 handleChange = (event) => { 39 this.setState({text:event.target.value}) 40 } 41 handleChangeDays = (event) => { 42 this.setState({days:event.target.value}) 43 } 44 handleChangeOrders = (event) => { 45 this.setState({value:event.target.value}) 46 } 47 48 handleSubmit (e) { 49 e.preventDefault(); 50 if (!this.state.text) return; 51 this.setState( 52 { 53 lists: [ 54 ...this.state.lists, 55 { 56 input: this.state.input, 57 value: this.state.value, 58 days: this.state.days 59 }], 60 input:"", 61 days:"", 62 value:"" 63 }); 64 }; 65} 66export default EditForm;

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

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

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

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

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

thyda.eiqau

2019/10/04 00:14

エラーの内容を質問本文に追記する形でご提示ください
og24715

2019/10/04 04:49

@babel/plugin-proposal-class-properties 使っているのであればアロー関数を使った関数プロパティはコンストラクタで bind(this) する糖衣構文になるのでコンストラクタでやってる bind(this) は不要です
guest

回答1

0

こんにちは

ご質問に挙げられている、AppLoop のコードを修正して編集できるようにしたコードを回答します。修正の要点は以下の4点です。

  1. 新規登録と編集とで、同じフォームを使うことができるので、EditFormは未使用
  2. lists の要素に、ユニークなid というプロパティを追加(9000はじまりの整数)
  3. 新規登録の入力中か、または既存アイテムの編集中かを示す state のプロパティを、真偽値のediting から、整数の selectedId に変更。selectedIdは編集対象のアイテムのid を表し、初期値の -1 はどれも編集対象になっていないことを示す。
  4. Loop は、stateを持たないので、クラスコンポーネントから関数コンポーネントに修正

以下に修正後の App.js と Loop.js のコードを挙げます。

App.js

jsx

1import React from 'react' 2import Loop from './Loop' 3import './list.css' 4 5const fixed = ["月曜日", "火曜日", "水曜日", "木曜日", "金曜日"] 6 7const INITIAL_ID = 9000 8const nextId = ((id) => (() => id ++))(INITIAL_ID) 9 10class App extends React.Component{ 11 constructor(props) { 12 super(props) 13 this.state = { 14 lists: [], 15 input: "", 16 value: "", 17 days: "", 18 selectedId: -1 19 } 20 this.handleSubmit = this.handleSubmit.bind(this) 21 this.handleDelete = this.handleDelete.bind(this) 22 this.handleChangeEditing = this.handleChangeEditing.bind(this) 23 } 24 25 render () { 26 const { days, value, input, selectedId, lists } = this.state 27 return ( 28 <div> 29 <h1>時間割</h1> 30 <form> 31 <select 32 value={days} 33 onChange={this.handleChangeDays} 34 > 35 <option value="">---</option> 36 <option value="月曜日">月曜日</option> 37 <option value="火曜日">火曜日</option> 38 <option value="水曜日">水曜日</option> 39 <option value="木曜日">木曜日</option> 40 <option value="金曜日">金曜日</option> 41 </select> 42 43 <select 44 value={value} 45 onChange={this.handleChangeOrders}> 46 <option value="">---</option> 47 <option value="1限:">1限</option> 48 <option value="2限:">2限</option> 49 <option value="3限:">3限</option> 50 <option value="4限:">4限</option> 51 <option value="5限:">5限</option> 52 </select> 53 <div> 54 <input 55 onChange={this.handleChange} 56 type="text" 57 value={input} 58 /> 59 60 <button onClick={this.handleSubmit}>保存</button> 61 <button onClick={this.handleDelete}>削除</button> 62 </div> 63 </form> 64 <div className="p-list"> 65 {fixed.map((l) =>( 66 <div className="list" key={l}> 67 <p>{l}</p> 68 <div> 69 <Loop 70 onClick={this.handleChangeEditing} 71 selectedId={selectedId} 72 lists={lists.filter(item => item.days === l)} 73 /> 74 </div> 75 </div> 76 ))} 77 </div> 78 </div> 79 ); 80 } 81 82 handleChangeEditing (itemId) { 83 const { lists, selectedId } = this.state 84 if (selectedId === itemId) { 85 this.setState({ selectedId: -1, days: "", value: "", input: "" }) 86 } else { 87 const { days, value, input } = lists.find(e => e.id === itemId) 88 this.setState({ selectedId: itemId, days, value, input }) 89 } 90 } 91 92 handleDelete () { 93 this.setState({ 94 input: this.state.input, 95 value: this.state.value, 96 days: this.state.days}) 97 } 98 99 handleChange = (event) => { 100 this.setState({input:event.target.value}) 101 } 102 103 handleChangeDays = (event) => { 104 this.setState({days:event.target.value}) 105 } 106 107 handleChangeOrders = (event) => { 108 this.setState({value:event.target.value}) 109 } 110 111 handleSubmit (e) { 112 e.preventDefault() 113 const { lists, input, value, days, selectedId } = this.state 114 if (!input) return 115 116 let nextLists; 117 if (selectedId >= INITIAL_ID) { 118 nextLists = lists.map(e => 119 e.id === selectedId ? { id: e.id, input, value, days } : e 120 ) 121 } else { 122 nextLists = [ ...lists, { id: nextId(), input, value, days } ] 123 } 124 125 this.setState( { lists: nextLists, input: "", days: "", value: "", selectedId: -1 }) 126 } 127} 128 129export default App 130 131

Loop.js

jsx

1import React from 'react' 2 3const Loop = ({ lists, selectedId, onClick }) => ( 4 <div> 5 {lists.map((l) =>( 6 <div key={l.id}> 7 <div 8 onClick={() => { onClick(l.id) }} 9 className={l.id === selectedId ? 'selected' : ''} 10 > 11 {l.value}{l.input} 12 </div> 13 </div> 14 ))} 15 </div> 16) 17 18export default Loop 19

上記に加えて、編集中のアイテムがどれなのか分かりやすくするため、以下を list.css に追加しました。

list.css

css

1.selected { background-color: #aaa; }

上記の修正後のコードで何か不明点などあれば、コメント頂ければと思います。
以上、参考になれば幸いです。

追記

Loop の下記の箇所を修正しました。

  • 修正前: <div key={l.days}>
  • 修正後: <div key={l.id}>

修正前のままだと、同じ曜日に2つ以上のアイテムがあるとき、「keyが重複している要素がある」旨の警告がコンソールに出力されます。

追記2

上記に記載した修正後のコードから、さらにリファクタリングしたコードを挙げておきます。 App は以下のようなコードになりました。

src/containers/App.js

jsx

1import React from 'react' 2import { Container, LessonForm, LessonsByDaysOfWeek, Title } from '../components' 3import { nextId, INITIAL_ID } from '../utils' 4import '../css/list.css' 5 6const initialForm = { 7 id: 0, // 有効なidの値はINITIAL_ID以上 8 subject: "", 9 period: 0, // 1: 1限, 2: 2限, ・・・ 5: 5限 10 dayOfWeek: -1, // 0: "月曜日", 1: "火曜日" ・・・ 4: "金曜日" 11} 12 13class App extends React.Component{ 14 constructor(props) { 15 super(props) 16 this.state = { 17 lessons: [], 18 form: { ...initialForm } 19 } 20 } 21 22 handleSave = () => { 23 const { lessons, form } = this.state 24 if (!form.subject) return 25 26 const nextLessons = form.id >= INITIAL_ID 27 ? lessons.map(e => e.id === form.id ? { ...form } : e) 28 : [ ...lessons, { ...form, id: nextId() } ] 29 30 this.setState( { lessons: nextLessons, form: { ...initialForm } }) 31 } 32 33 handleChange = event => { 34 const { name, value } = event.target 35 const form = { 36 ...this.state.form, 37 [name]: ['dayOfWeek', 'period'].includes(name) ? +value : value 38 } 39 this.setState({ form }) 40 } 41 42 handleSelect = lesson => { 43 this.setState( 44 { form: { ...(this.state.form.id === lesson.id ? initialForm : lesson) } } 45 ) 46 } 47 48 handleDelete = () => { 49 // TODO: 後で作成 50 } 51 52 render () { 53 return ( 54 <Container> 55 <Title text="時間割" /> 56 <LessonForm 57 {...this.state.form} 58 handleChange={this.handleChange} 59 handleSave={this.handleSave} 60 handleDelete={this.handleDelete} 61 /> 62 <LessonsByDaysOfWeek 63 lessons={this.state.lessons} 64 selectedId={this.state.form.id} 65 handleSelect={this.handleSelect} 66 /> 67 </Container> 68 ); 69 } 70} 71 72export default App 73

上記の App と、import される他のコンポーネント含めて、以下のGitHub レポジトリに上げてあります。

以下は、このレポジトリに関しての補足説明です。

  • ベースを create-react-app で作成しており、以下のコマンドでアプリを起動できます。

shell

1git clone https://github.com/jun68ykt/q215244.git 2cd q215244 3yarn install 4yarn start

v1.0: 質問に挙げられていたコード
v2.0: 編集できるようにして、回答に記載
v3.0: リファクタリング版

ご興味あれば、レポジトリをcloneしてSourcetree などで各修正コミットの内容を追って頂き、どういう意図の修正か不明な点などがあれば、コメントから質問頂ければ幸いです。

投稿2019/10/04 16:52

編集2019/10/06 05:03
jun68ykt

総合スコア9058

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問