ちゃんなるぶろぐ

エンジニア5年生🧑‍💻 オライリーとにらめっこする毎日。

【5分でわかる!】DOM構成に全く影響を与えずにReactコンポーネントを実行する

どうも、ちゃんなるです!

今回はReactに関してです(ソースコード on Github)。

概要

今回の内容は実務で使うことは少ないかもしれません。「そんな考え方もあるんやな」程度に聞いてください。

今回やりたいこと

DOM構成を変えることなくReactコンポーネント内の処理を実行させる。

(あれReactって画面を作るためのフレームワークやないっけ?本末転倒やん。。。という指摘は目を瞑ってください笑)

実現方法

DOM要素を新しく作り、それを起点にReactのレンダラーを実行する。

すなわち、ReactDOM.createRoot()に画面表示用のHTMLファイルに記述されてないDOM要素を渡してあげる。

下記の例ではcreateElement()tentativeElementというdiv要素を新規作成し、それに対してレンダリングをしています。

// index.jsx

import ReactDOM from 'react-dom/client'
import { App } from './App'

const tentativeElement = document.createElement('div')
const tentativeRoot = ReactDOM.createRoot(tentativeElement)
tentativeRoot.render(
  <App />
)

これにより、例えば下記のようにAppコンポーネント内の任意の処理を実行できます👍

// App.jsx

export const App = () => {
  /*任意の処理を記述する*/
  console.log("Since the DOM element we're rendering to isn't visible anywhere, ")
  console.log("returning a JSX element here won't be rendered.")

  /*ここでJSXを返しても良いが、どのみちレンダリングされないのでnullとしました。*/
  return null
}

Reactコンポーネント内部なのでReact固有の処理、例えばReactのHooks*1が使えます👍

もちろんreturnの際に他の関数コンポーネントを返すこともできるので、複数の関数コンポーネント内の処理も行えます。

// App.jsx

export const App = () => {
  /*任意の処理を記述する*/

  return (
    <Contents1 />
    <Contents2 />
    <Contents3 />
  )
}

const Contents1 = () => { ... }
const Contents2 = () => { ... }
const Contents3 = () => { ... }

まとめ

ブラウザ上に表示されるDOM要素に対してではなく新たに作成したDOM要素に対してレンダリングすることにより、画面に影響を与えることなくReactコンポーネントの処理を行えました。

この手法を使うことはあまりないかもしれませんがこんな技もあると思ってもらえれば🙋‍♂️

ちなみにですが新たに作成したDOM要素をブラウザ上に表示されるDOM要素の子要素として挿入(appendChild())してあげれば、簡単に画面に影響させられます👌

// index.jsx

import ReactDOM from 'react-dom/client'
import { App } from './App'

const tentativeElement = document.createElement('div')
document.getElementById('root').appendChild(tentativeElement) // 例えば、この行を追加する
const tentativeRoot = ReactDOM.createRoot(tentativeElement)
tentativeRoot.render(
  <App />
)

環境

実装や動作確認の際に使ったツールたちです。

OS macOS Monterey Version 12.5
Node.js v18.6.0
create-react-app v5.0.1

*対象のアプリはcreate-react-appを用いて作成しました。

関連資料

【5分でわかる!】Reactで複数のDOM要素にレンダリングする

どうも、ちゃんなるです!

今回はReactに関して書きます(ソースコード on Github)。

概要

React.jsの基本的なレンダリング

基本的にReactでは、下記のようなroot要素を起点にし、その子要素はReactコンポーネントで表現すると思います。

<div id="root" >
</div>

具体的には、起点にしたい単一のDOM要素をgetElementById()querySelector()等で取得し、それをReactDOM.createRoot()に渡してあげます。

import ReactDOM from 'react-dom/client';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
)
root.render(
  /*<Reactコンポーネントを記述>*/
)

今回やりたいこと

ですが最近私は、例えば下記のような複数の隣接していないDOM要素を起点にしたいと思いました。 *該当箇所にはid="selected"を与えてます。

<div>
  <div id="selected" >
  </div>
  <div>
    ...
  </div>
  <div id="selected" >
  </div>
</div>

対象は例えばこんな画面です。Hereとなっている部分を対象のDOM要素とします。

https://raw.githubusercontent.com/naruwo-github/react-sandbox/main/rendering-in-multiple-places/asset/html.png

実現方法

起点としたい複数のDOM要素を取得し、それをReactDOM.createRoot()へ渡してあげればOKです👍

import ReactDOM from 'react-dom/client'

const domContents = document.querySelectorAll('#selected')

domContents.forEach(element => {
  const root = ReactDOM.createRoot(element)
  root.render(
    /*<Reactコンポーネントを記述>*/
  )
})

結果は例えばこのようになります。

https://raw.githubusercontent.com/naruwo-github/react-sandbox/main/rendering-in-multiple-places/asset/html-inserted-react.png

まとめと課題

複数の離れたDOM要素を起点にReactでレンダリングしたい場合、それら要素を取得してReactDOM.createRoot()へ渡してあげればOK!

ただ、今回はPropsやStateに関して触れてませんね👀 なので次回はPropsやStateを扱うことを考慮して複数のDOM要素にレンダリングする方法を紹介しようと思います!

環境

実装や動作確認の際に使ったツールたちです。

OS macOS Monterey Version 12.5
Node.js v18.6.0
create-react-app v5.0.1

*対象のアプリはcreate-react-appを用いて作成しました。

関連資料

【3分でわかる!】お金と心理学②〜書籍『お金に支配されない13の真実』より〜

読み終えるまで約3分

どうも、ちゃんなるです。

今回紹介するのはこの本!

『お金に支配されない13の真実』

この本から得られるもの

多くの心理学研究に基づいた、科学的なお金の知識。

「人は、どのような状況下で、どのようなことを考え、どのように振る舞うのか」という様々な実例をもとに紹介されています。

今回紹介する3つの内容

①報酬より褒め言葉

いくつかの調査から、次のことがわかっています。

「報酬は、作業の生産性を上げれないだけでなく、作業に感じる楽しみを奪う可能性がある」

(調査の内容に関しても詳細に書かれていたので、気になる方はぜひ本書を手に取ってみてください!)

また、『スキナーの理論』というものがあります。

  • モチベーションのない作業の達成に報酬を払うのは良い
    • 例えば、「掃除をしたらお小遣いをあげる」とした場合、掃除をこなす確率は高まります。
  • モチベーションのあるものの達成に報酬を払うのは有害である
    • 例えば、「上手に絵を描いたらお小遣いをあげる」とした場合、絵を描くこと自体に楽しみを感じにくくなり、お小遣いを上げなくなった場合に絵を描くのをやめてしまう確率が非常に高いです。

モチベーション高く行動している人に対しては、報酬ではなく褒め言葉を与えるようにしましょう!その後も継続して取り組んでくれるようになるはずです。

②お金と慣れ

急激に富を得る/失うことによって生活水準が変わったとしても、その嬉しさ/悲しさは長くは続きません。

下記のような調査結果もあります。

  • 宝くじの高額当選者(億単位で当選した人々)に関して
    • 一年後、過半数当選前より不幸になったと回答
    • 一定期間後、主観的な人生の満足度は、事故で手足を失ってしまった人と比べて差がほとんどない

人の体には生理機能を一定に保とうとするホメオスタシスという機能があります。メンタルにもホメオスタシスが機能し、一定の状態に保とうとする力が働くのです。(心理学的ホメオスタシスとも)

ただ、その一定の状態に戻るまでのスピードに差が見られます。富を得て幸せになる方が、富を失って不幸になることに比べて早く慣れてしまうようです。

お金を持ったらすぐに生活水準を上げてしまうのはNGですね。ゆっくりと生活水準を上げたり、豪遊する頻度を極力抑えることで、幸せが長続きするかもしれません。

また、急に富を失ってしまった場合でも、時間がメンタルを回復させてくれると言えます。今辛い状況にいる場合でも、諦めず今日を生きてみてはどうでしょうか?

③貧困がもたらすもの

悲しい事実があります。貧困は次のデメリットをもたらします。

  • IQが下がる
  • 判断をミスりやすくなる
  • 同情されない

お金が足りないと感じると、お金の不安が常に頭の中に居座り、私たちの判断力を奪います。

判断力が落ちると、お金に関する判断でミスをする場合があります。例えば、後先考えず衝動買いをしたり、不必要なものを買ったり、ひどいものでは高金利の借金をしたり、リボ払いをしたり。。。

そして、そのミスのせいでまたお金が足りなくなり、IQがさがり、、、負のスパイラルです。

以前紹介した本に、貧困(お金の欠乏)に関する行動経済学に関するものがあったので、こちらも見てみてください! お金・時間・人間関係への「足りない…」という感情は、負のスパイラルです… chan-naru.hatenablog.com

貧しいと人は同情するのではないか?と思う人もいるでしょう。 もちろん、同情する人もいます。

しかし、残念ながら、科学的にはそうではないのです。

人は自分と違う人に対して嫌悪感を持つ生き物です。自分と違うコミュニティに属する人、異国の人々に対して差別やいじめを行う人がいますが、彼ら彼女らの持つ心理がこの嫌悪感です。

平均的な人々より貧しくなってしまうと、いわゆる貧者になってしまうと、嫌悪の対象になってしまうかもしれません。ひどく困窮して頭が回らなくなってしまう前に、できることを考えてみてはどうでしょうか?

まとめ

  • 報酬を与えても生産性は上がらず、むしろモチベーションを奪ってしまうかも。モチベーション高く行動している人は褒めよう。
  • 人は「慣れる」生き物なので、急激に生活を変えるのは避けよう。
  • 貧困は知能を下げ、判断力を奪い、人に嫌われやすくなる。。。

書籍情報

Mind over Money 193の心理研究でわかったお金に支配されない13の真実 [ Claudia Hammond ]

価格:1,760円
(2022/5/1 18:40時点)
感想(2件)

  • 【書籍名】Mind over Money 193の心理研究でわかったお金に支配されない13の真実
  • 【著者名】Claudia Hammond, 木尾 糸己
  • 【出版社】あさ出版
  • 【出版日】2017年6月23日頃
  • 【ページ数】334