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

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

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

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

React.js

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

Q&A

解決済

1回答

3035閲覧

Reactについて、inputで入力した数だけ画像をループさせる方法

kenkenp

総合スコア7

JavaScript

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

React.js

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

0グッド

0クリップ

投稿2017/06/12 06:22

###前提・実現したいこと
Reactについて、inputで入力した数だけ画像をループさせる方法がわかりません。
解決策や原因をご存知の方がいらっしゃれば、教えていただけないでしょうか。
よろしくお願いいたします。

イメージ説明

###発生している問題
React勉強中の初心者です。
inputでカラム数を入力したら、プレビューにカラム数ぶんの画像が繰り返し出力されるようにしたいのですが、うまくできません。
カラム数にどの数字を入力をしても画像が1つしか出てこず、繰り返しがうまくいっていないのだと考えています。
renderメソッド内やJSX内に書いてみましたが結果は同じでした。

コンポーネントのライフサイクルの問題もあるかと思い調べていますが、なかなか解決できないでいます。

コンパイラやブラウザの開発ツールでエラーはでていません。

###該当のソースコード

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>React Calculate Padding</title> 8</head> 9<body> 10 <div id="app"></div> 11 <script src="dist/bundle.js"></script> 12</body> 13</html>

Javascript

1import React from 'react'; 2import { render } from 'react-dom'; 3 4class App extends React.Component { 5 6 constructor() { 7 super(); 8 this.state = { 9 baseWidthValue: 1000, 10 columnValue: 0, 11 paddingValue: 20, 12 }; 13 } 14 15 onChangebaseWidth(e) { 16 this.setState({ baseWidthValue: e.taget.value }); 17 } 18 19 onChangeColumn(e) { 20 this.setState({ columnValue: [e.target.value] }); 21 } 22 23 onChangePadding(e) { 24 this.setState({ paddingValue: e.target.value }); 25 } 26 27 previewElement() { 28 const list = []; 29 const column = this.state.columnValue; 30 31 const inputPadding = this.state.paddingValue; 32 const totalPadding = (this.state.columnValue - 1) * inputPadding; 33 const padding = totalPadding / this.state.columnValue; 34 const paddingVal = padding / (this.state.columnValue - 1); 35 const elemPadding = padding - (paddingVal * 1); 36 37 for (let i = 0; i < column.length; i++) { 38 list.push( 39 <div 40 className='preview-element' 41 key='columnValue' 42 > 43 <img src="img/box.gif" width={100} height={100} /> 44 <p className='text1'> 45 {'左:' + (Math.floor((padding - elemPadding) * this.state.baseWidthValue) / this.state.baseWidthValue) + 'px'} 46 </p> 47 <p className='text2'> 48 {'右:' + (Math.floor(elemPadding * this.state.baseWidthValue) / this.state.baseWidthValue) + 'px'} 49 </p> 50 </div> 51 ); 52 } 53 return list; 54 } 55 56 render() { 57 return ( 58 <div> 59 <div> 60 <h1>カラム間のpadding余白計算</h1> 61 <form> 62 <p> 63 <label htmlFor='baseWidth'>親要素の横幅:</label> 64 <input type='text' className='baseWidth' value={this.state.baseWidthValue} onChange={this.onChangebaseWidth.bind(this)} />px 65 </p> 66 <p> 67 <label htmlFor='column'>カラム数:</label> 68 <input type='number' className='column' value={this.state.columnValue} onChange={this.onChangeColumn.bind(this)} /> 69 </p> 70 <p> 71 <label htmlFor='padding'>カラム間の余白:</label> 72 <input type='number' className='padding' value={this.state.paddingValue} onChange={this.onChangePadding.bind(this)} />px 73 </p> 74 </form> 75 </div> 76 77 <div> 78 <h2>プレビュー</h2> 79 <div> 80 {this.previewElement()} 81 </div> 82 </div> 83 </div> 84 ); 85 } 86 87} 88 89render( 90 <App />, 91 document.getElementById('app') 92);

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2017/06/13 20:34 編集

{this.previewElement()} ここで配列がリターンされていると思うのですが、波カッコで配列を囲むと配列の中のJSXが自動で展開されるのでしたっけ?
kenkenp

2017/06/19 04:03

お返事が遅くなりすみません。previewElementメソッドの中で先に配列に要素を追加しておいて、{this.previewElement()}で出力するようにしています。自動で展開というより、繰り返されたものをそのままいれています。
guest

回答1

0

ベストアンサー

onChangeColumn(e) { this.setState({ columnValue: [e.target.value] }); }

columnValueに配列として数値を代入しているのが一番悪い箇所だと感じています。
これだとthis.state.columnValue.lengthはいつでも1になってしまいます。

いっそのことcolumnValueには数値を入れたほうがいいでしょう。

onChangeColumn(e) { this.setState({ columnValue: Number(e.target.value) }); }

投稿2017/06/16 03:04

sakapun

総合スコア888

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

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

kenkenp

2017/06/19 04:45 編集

お返事が遅くなりすみません。ご回答ありがとうございます。 おっしゃる通り、onChangeColumnメソッドのe.target.valueを配列にしているのが原因の一つでした。 その他の原因がpreviewElementメソッドの中に2つありました。 1つ目はforの条件式にlengthをつけることで上記とあわせて配列の要素数を取得していたこと(おっしゃる通り1にしかならない)。 2つ目はkeyをrenderメソッドの外で使っていたので同じkeyが繰り返されていたことでした。 なので結果的にコードを以下のように修正したら、意図したとおり繰り返し表示ができました。 ``` onChangeColumn(e) { this.setState({ columnValue: e.target.value }); // 初期化で数値リテラルをいれているので、とりあえず配列をやめるだけにしました } ``` ``` previewElement() { const list = []; const column = this.state.columnValue; const inputPadding = this.state.paddingValue; const totalPadding = (this.state.columnValue - 1) * inputPadding; const padding = totalPadding / this.state.columnValue; const paddingVal = padding / (this.state.columnValue - 1); const elemPadding = padding - (paddingVal * 1); for (let i = 0; i < column; i++) { // .length削除 list.push( <div className='preview-element' // key='columnValue' // 削除 > <img src="img/box.gif" width={100} height={100} /> <p className='text1'> {'左:' + (Math.floor((padding - elemPadding) * this.state.baseWidthValue) / this.state.baseWidthValue) + 'px'} </p> <p className='text2'> {'右:' + (Math.floor(elemPadding * this.state.baseWidthValue) / this.state.baseWidthValue) + 'px'} </p> </div> ); } return list; } ``` 試行錯誤していたので遅くなりましたが、ヒントをいただきましてありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問