動的に描画するコンポーネントにある要素を、描画するたびに違う位置に配置したいです。
下記はサンプルです。
ランダムボタンを押すとランダムコンポーネントが描画されます。
ランダムコンポーネントにある赤ボタンにonMouseDown
するとクリック中と表示し、onMouseUp
するとクリック中の表示が消えます。
ランダムコンポーネントにあるトップボタンを押すと、ランダムコンポーネントをアンマウントします。
発生している問題
コンポーネントの描画毎に赤ボタンをランダムに配置できていますが、マウスイベントを実行するたびに、赤ボタンの位置が変更してしまいます。
マウスイベントでクリック中のstateを更新しているため、stateの更新による再レンダーで赤ボタンが移動しているかと思います。
stateの管理はHooksを利用しています。
実現したいこと
マウスイベントによって赤ボタンが移動することがないようにしたいです。
それを踏まえた上で、コンポーネントの描画毎に赤ボタンをランダムに配置したいです。
ソースコード
・Random.jsx
jsx
1/** @jsx jsx */ 2import React, { useState } from "react"; 3import { jsx, css } from "@emotion/core"; 4 5const Random = ({ setRandom }) => { 6 const click = () => { 7 setRandom(false); 8 }; 9 10 const [clicking, setClicking] = useState(false); 11 const down = () => setClicking(true); 12 const up = () => setClicking(false); 13 14 const randomAreaWidth = window.screen.width; 15 const randomAreaHight = window.screen.height - 100; 16 let maxTop = randomAreaWidth * 0.3; 17 let maxLeft = randomAreaHight * 0.2; 18 const top = Math.random() * (maxTop + 1); 19 const left = Math.random() * (maxLeft + 1); 20 const button = css` 21 background: red; 22 border: none; 23 color: white; 24 cursor: pointer; 25 width: 60px; 26 height: 60px; 27 transform: translate(${top}px, ${left}px); 28 `; 29 30 return ( 31 <React.Fragment> 32 <header css={header}> 33 <h2>ランダム</h2> 34 <button onClick={click}>トップ</button> 35 {clicking === true && <p>クリック中</p>} 36 </header> 37 <hr /> 38 <button css={button} onMouseDown={down} onMouseUp={up}> 39 ボタン 40 </button> 41 </React.Fragment> 42 ); 43}; 44 45const header = css` 46 display: flex; 47 align-items: center; 48 height: 50px; 49 h2, 50 button { 51 margin-right: 16px; 52 } 53`; 54 55export default Random; 56
・App.jsx
jsx
1/** @jsx jsx */ 2import React, { useState } from "react"; 3import { jsx } from "@emotion/core"; 4import Random from "./Random"; 5 6export default function App() { 7 const [random, setRandom] = useState(false); 8 const click = () => { 9 setRandom(true); 10 }; 11 12 return ( 13 <React.Fragment> 14 <h1>トップ</h1> 15 <button onClick={click}>ランダム</button> 16 {random === true && <Random setRandom={setRandom} />} 17 </React.Fragment> 18 ); 19}
使用しているCSSフレームワーク
EmotionをCSS in JS記法で使用しています。
試したこと
1. 赤ボタンのCSSをランダムコンポーネントの外に移す
サンプル
マウスイベントのたびに赤ボタンが移動することは無くなりましたが、コンポーネントの描画毎にランダム配置ができず、毎回同じ位置に描画されます。
初回描画時のみランダムに配置できています。
2. クリック中かどうかをstateで管理しない
サンプル
再レンダーを防ぐためにクリック中かどうかをstateで管理せず、マウスダウンとアップのイベントそれぞれでtrueとfalseを変数に代入することで、マウスイベント毎の赤ボタンの移動は無くなりました。
しかし、クリック中メッセージの表示の切り替えができません。
3. 試したこと2 + クリック中メッセージの表示をCSSで切り替える
サンプル
クリック中メッセージの表示の切り替えを、
jsx
1{clicking && <p>クリック中</p>}
上記のような論理 && 演算子によるインライン Ifではなく、下記のようにCSSで切り替える方向で試してみました。
jsx
1const clickingMessage = css` 2 display: ${clicking ? "block" : "none"}; 3`;
しかし2.と同じでクリック中かどうかをstateで管理していないため、displayの三項演算子は描画時しか実行されませんでした、
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/10 00:35