【3】React Nativeでテキストエディタを作ってみる!【右往左往編】

こんにちは!かたつむり(@Katatumuri_nyan)です!

Reactを触ってみて、サイト的なものは作れるようになりました(*´ω`)
そこで、次はReactNativeを触ってみようと思い、簡単なテキストエディタを作成しようと企んでおります(笑)

環境構築があらかた終わったので、早速画面を作成してみたいと思います!

最初から見る↓
【1】React Nativeでテキストエディタを作ってみる!【下調べ編】【1】React Nativeでテキストエディタを作ってみる!【下調べ編】

前回を見る↓
【2】React Nativeでテキストエディタを作ってみる!【環境構築編】【2】React Nativeでテキストエディタを作ってみる!【環境構築編】

いきなりエラーから始まります…

picture 1

/usr/src/app/node_modules/react-native-web/node_modules/fbjs/lib/ExecutionEnvironment.js
Error: ENOENT: no such file or directory, open '/usr/src/app/node_modules/react-native-web/node_modules/fbjs/lib/ExecutionEnvironment.js'

これは前回の記事の最後にexpo upgradeしたせいですね…。
これ、react-native-webがインストールされてないってことかなぁ…。
と思い、確認するとありました。
でも
/usr/src/app/node_modules/react-native-web/node_modules/fbjs/lib/ExecutionEnvironment.jsはないですね…。

picture 2

よく見たら、expo upgradeのエラーが残っていました。
内容は同じっぽいですね。

picture 3
↑一応コンテナ側で確認するも、確かに/usr/src/app/node_modules/react-native-web/node_modules/fbjs/lib/ExecutionEnvironment.jsはない…。

react-native-webを入れなおしてみます。
yarn add react-native-webをしてインストール

picture 4

/usr/src/app/node_modules/react-dom/node_modules/scheduler/index.js
Module build failed: Error: ENOENT: no such file or directory, open '/usr/src/app/node_modules/react-dom/node_modules/scheduler/index.js'

次はこれ↑

yarn upgradeもしてみたけど、とくに変わらないので、Docker imageからbuildしなおすことにしました。expoの初期化はなし。

Google Chromeデベロッパーツールの拡張

やっと開発できるようになったので、デベロッパーツールでiPhoneとiPadの表示を確認しながらやっていきます。

picture 5

こんなことができたので( ..)φメモメモ

三点マークを押して、show device frameで一部のデバイスのフレームが表示されました。

今のディレクトリ構成

picture 6

App.jsがおそらくメインの枠になるので、これに合わせてコンポーネントを作っていきます。

ためしにテキストエリアを作成

そもそも、テキストエリアって、Inputエリアでいいのかな…?

とりあえず、TextArea.jsを作成し、App.jsに読み込んでみます。
素材は公式リファレンスから。

// App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import UselessTextInput from './components/TextArea';

export default function App() {
  return (
    <View style={styles.container}>
      <UselessTextInput
      value="Hello World!"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
// TextArea.js
import React, { Component } from 'react';
import { TextInput } from 'react-native';

export default function UselessTextInput(props) {
  const [value, onChangeText] = React.useState(props.value);

  return (
    <TextInput
      style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
      onChangeText={text => onChangeText(text)}
      value={value}
    />
  );
};

picture 7

とりあえず、文字は打てるようになりました(*´ω`)

テキストエディタパッケージを使用するも断念

React Native Editor

npm i react-native-editorしてみる。
互換性があれば使いたい。

ちょっと使ってみたけど、読み込みが遅すぎるので再起動したらエラー…
yarn installしろとのことなので、しておきました。

picture 8

/usr/src/app/node_modules/react-native-editor/src/RichToolbar.js  
Module not found: Can't resolve '../img/icon_format_bold.png' in '/usr/src/app/node_musr/src/app/node_modules/react-native-editor/src'

RichToolbar.jsの14行目くらいを以下に変更

function getDefaultIcon() {
    const texts = {};
    texts[actions.insertImage] = require('../img/icon_format_media@3x.png');
    texts[actions.setBold] = require('../img/icon_format_bold@3x.png');
    texts[actions.setItalic] = require('../img/icon_format_italic@3x.png');
    texts[actions.insertBulletsList] = require('../img/icon_format_ul@3x.png');
    texts[actions.insertOrderedList] = require('../img/icon_format_ol@3x.png');
    texts[actions.insertLink] = require('../img/icon_format_ol@3x.png');
    return texts;
}

picture 9

/usr/src/app/node_modules/react-native-editor/src/RichEditor.js    
react_native_1  
Module not found: Can't resolve 'react-native-webview' in '/usr/src/app/node_modules/react-native-editor/src'

次はこれなので、expo install react-native-webviewしてみる
WebView

やっぱりうまくいかない😢

react-native-editorは一旦やめて、自前で作ることにしました。

npm rm react-native-editor

試しに画面を作ってみる

React Nativeで任意のReact コンポーネントを使う方法
↑この方法でできそう…?
ということで、ちょっと自前で色々作ってみます。

picture 10

とりあえず、こんな感じです!
コードは以下。

// App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MyTextArea from './components/TextArea';
import MyPreview from './components/Preview';
import MyPanel from './components/Panel';
import './styles/style.css'

export default function App() {
  return (
    <View style={styles.container}>
      <div className="main_wrap">
        <MyPanel
        value="panel"
        />
        <MyTextArea
          placeholder="Hello World!"
          className="textarea_main"
        />
        <MyPreview
          value="ぷれびゅ~"
        />
      </div>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
// Panel.js
import React, { Component } from 'react';
import { StyleSheet, Text} from 'react-native';

export default function MyPanel(props) {
  // const [value, onChangeText] = React.useState(props.value);

  return (
      <Text style={styles.innerText}>
        {props.value}
      </Text>

  );
};

const styles = StyleSheet.create({
  baseText: {
    fontWeight: 'bold'
  },
  innerText: {
    color: 'red'
  }
});
// TextArea.js
import React, { Component } from 'react';
import { StyleSheet, Text} from 'react-native';

export default function MyPanel(props) {
  // const [value, onChangeText] = React.useState(props.value);

  return (
      <Text style={styles.innerText}>
        {props.value}
      </Text>

  );
};

const styles = StyleSheet.create({
  baseText: {
    fontWeight: 'bold'
  },
  innerText: {
    color: 'red'
  }
});

StyleSheetの扱いが難しいですが、できそうな気がしてきました。

ホットリロード問題

作業中にCHOKIDAR_USEPOLLING=trueでのホットリロードが重すぎて悲しくなってきたので、改善したいと思います。

docker-expo

↑こちらによると、Docker環境ではホットリロードが効かないと書いています。
(そうだと思ってた)
Watchmanが必要とのことなので、インストールしてみたいと思います。

Watchmanをインストール

公式ドキュメントを見つつ、Watchmanをインストールしていきます。

yarnを使っているのでyarn add fb-watchmanでインストール。

CHOKIDAR_USEPOLLING=trueを削除して、docker-compose upしなおします。

公式ドキュメントからもインストールの必要ありました。

$ # use the latest stable release
$ git clone https://github.com/facebook/watchman.git -b v4.9.0 –depth 1
$ cd watchman
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

↑こちら真似していきます!

gitがないのでapk add gitします。

git clone https://github.com/facebook/watchman.git
cd watchman
./autogen.sh

python3がないといわれたのでapk add python3します。

./autogen.sh
Building Boost.Build engine with toolset ...
Failed to build Boost.Build build engine
Consult 'bootstrap.log' for more details
Command '['/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/extracted/boost-boost_1_69_0.tar.bz2/boost_1_69_0/bootstrap.sh', '--prefix=/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/installed/boost-EknnPlrWpvg6lQTh9KAzVMJn6jfCvnM2969L_tvo3dg']' returned non-zero exit status 1.
!! Failed

エラー(´;ω;`)
react_native\watchman\bootstrap.logを見つけたので見てみます。

###
### Using 'cc' toolset.
###
rm -rf bootstrap
mkdir bootstrap
cc -o bootstrap/jam0 command.c compile.c constants.c debug.c execcmd.c frames.c function.c glob.c hash.c hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c object.c option.c output.c parse.c pathsys.c regexp.c rules.c scan.c search.c subst.c timestamp.c variable.c modules.c strings.c filesys.c builtins.c class.c cwd.c native.c md5.c w32_getreg.c modules/set.c modules/path.c modules/regex.c modules/property-set.c modules/sequence.c modules/order.c execunix.c fileunix.c pathunix.c
./build.sh: line 17: cc: not found

ccがないみたいですね。
alpinelinux: install failed: cc: Command not found
↑を参考に、apk add build-baseします。

もう一度↓

./autogen.sh
Command '['/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/extracted/boost-boost_1_69_0.tar.bz2/boost_1_69_0/b2', '-j4', '--prefix=/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/installed/boost-eYmU91RK2GtAWHdVNRfDHnGhe-s7cWgFxzY4yPNB4yo', '--builddir=/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/build/boost-eYmU91RK2GtAWHdVNRfDHnGhe-s7cWgFxzY4yPNB4yo', '--with-atomic', '--with-chrono', '--with-container', '--with-context', '--with-contract', '--with-coroutine', '--with-date_time', '--with-exception', '--with-fiber', '--with-filesystem', '--with-graph', '--with-graph_parallel', '--with-iostreams', '--with-locale', '--with-log', '--with-math', '--with-mpi', '--with-program_options', '--with-python', '--with-random', '--with-regex', '--with-serialization', '--with-stacktrace', '--with-system', '--with-test', '--with-thread', '--with-timer', '--with-type_erasure', '--with-wave', 'link=static', 'runtime-link=shared', 'variant=release', 'threading=multi', 'debug-symbols=on', 'visibility=global', '-d2', 'install']' returned non-zero exit status 1.
!! Failed

(´;ω;`)
試しに/tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/extracted/boost-boost_1_69_0.tar.bz2/boost_1_69_0/b2を打ってみます。

Unable to load Boost.Build: could not find "boost-build.jam"
---------------------------------------------------------------
BOOST_ROOT must be set, either in the environment, or
on the command-line with -sBOOST_ROOT=..., to the root
of the boost installation.

Attempted search from /usr/src/app/watchman up to the root
at /tmp/fbcode_builder_getdeps-ZusrZsrcZappZwatchmanZbuildZfbcode_builder-root/extracted/boost-boost_1_69_0.tar.bz2/share/boost-build
and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: /usr/share/boost-build.
Please consult the documentation at 'http://www.boost.org'.

ついでにDockerfile変えときました。

FROM node:14-alpine

WORKDIR /usr/src/app/

RUN apk update && apk add bash &&\
    apk add git &&\
    apk add python3 &&\
    apk add build-base

RUN yarn global add expo-cli

イメージからビルドしなおして、以下を再び行います。
watchmanディレクトリを一度消しました。)

git clone https://github.com/facebook/watchman.git -b v4.9.0 --depth 1
cd watchman
./autogen.sh
your system lacks libtoolize

↑の様なエラーが出たので、libtoolを入れないといけないみたいですね。
apk add libtoolをDockerfileに追加します。

ビルド後、コンテナを起動しなおして、再び以下を行います。

cd watchman
./autogen.sh
libtoolize:   error: One of these is required:
libtoolize:                 gm4 gnum4 m4
libtoolize:   error: Please install GNU M4, or 'export M4=/path/to/gnu/m4'.

GNU M4をインストールします!
apk add m4これもDockerfileに追加します。

↓やりなおし。

git clone https://github.com/facebook/watchman.git -b v4.9.0 --depth 1
cd watchman
./autogen.sh
./autogen.sh: line 16: aclocal: command not found

aclocalいれます!
How to install aclocal in ubuntu14.04によると、automakeを入れたらいいみたいなので、rootに戻ってapk add automakeします。

再び…

cd watchman
./autogen.sh
sh: autom4te: not found
aclocal: error: echo failed with exit status: 127

autom4teない!入れます!
autoconfに入ってるみたいですね!
apk add autoconf

再び…

cd watchman
./autogen.sh
pkg-config appears to be missing (not available to autoconf tools)
please install the pkg-config package for your system.

pkg-configないwwwないもの多すぎん?w
pkgconfigこれっぽい。apk add pkgconfig入れてみます。

再び…

cd watchman
./autogen.sh

何も反応がなく、できたっぽいので次に進みます。

./configure
make
make install

picture 11
いけたかな?

make
(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /usr/src/app/watchman/missing autoheader)
rm -f stamp-h1
touch config.h.in
cd . && /bin/sh ./config.status config.h
config.status: creating config.h
config.status: config.h is unchanged
make  all-am
make[1]: Entering directory '/usr/src/app/watchman'
  CXX      watchman-ChildProcess.o
  CXX      watchman-ContentHash.o
ContentHash.cpp:13:10: fatal error: openssl/sha.h: No such file or directory
   13 | #include <openssl/sha.h>
      |          ^~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [Makefile:3312: watchman-ContentHash.o] Error 1
make[1]: Leaving directory '/usr/src/app/watchman'
make: *** [Makefile:1264: all] Error 2

watchman builds on Linux require OpenSSL, but isn’t clearly stated in the docs
↑こちらよりapk add libressl-dev

再度以下を行います!

cd watchman
make
fstype.cpp:18:10: fatal error: linux/magic.h: No such file or directory
   18 | #include <linux/magic.h>
      |          ^~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [Makefile:3522: watchman-fstype.o] Error 1
make[1]: Leaving directory '/usr/src/app/watchman'
make: *** [Makefile:1264: all] Error 2

linux/magic.hないいい!
fstype.c:18:25: error: linux/magic.h: No such file or directory make[1]: *** [watchman-fstype.o]
kernel-headersを入れるといいらしい。
linux-headersぽいので入れます。apk add linux-headers

再度以下を行います!

cd watchman
make
scm/Mercurial.cpp: In constructor 'watchman::Mercurial::infoCache::infoCache(std::string)':
scm/Mercurial.cpp:16:40: error: 'void* memset(void*, int, size_t)' clearing an object of non-trivial type 'struct watchman::FileInformation'; use assignment or value-initialization instead [-Werror=class-memaccess]
   16 |   memset(&dirstate, 0, sizeof(dirstate));
      |                                        ^
In file included from scm/Mercurial.h:10,
                 from scm/Mercurial.cpp:3:
./FileInformation.h:18:8: note: 'struct watchman::FileInformation' declared here
   18 | struct FileInformation {
      |        ^~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[1]: *** [Makefile:4446: scm/watchman-Mercurial.o] Error 1
make[1]: Leaving directory '/usr/src/app/watchman'
make: *** [Makefile:1264: all] Error 2

!?
v4.9.0 compile failure on Debian unstable
↑を参考に./configure --enable-lenientしてみる。

再度以下

make
make install
gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Os -fomit-frame-pointer -g -Os -fomit-frame-pointer -g -Os -fomit-frame-pointer -g -DTHREAD_STACK_SIZE=0x100000 -fPIC -I/usr/include/python3.8 -c pywatchman/bser.c -o build/temp.linux-x86_64-3.8/pywatchman/bser.o
pywatchman/bser.c:31:10: fatal error: Python.h: No such file or directory
   31 | #include <Python.h>
      |          ^~~~~~~~~~
compilation terminated.
error: command 'gcc' failed with exit status 1
make[1]: *** [Makefile:5596: py-build] Error 1
make[1]: Leaving directory '/usr/src/app/watchman'
make: *** [Makefile:1264: all] Error 2

./configure --without-python --enable-lenientしてみます!

再度以下

make

できたっぽいので↓します!

make install
make[1]: Entering directory '/usr/src/app/watchman'
 ./install-sh -c -d '//usr/local/bin'
  /bin/sh ./libtool   --mode=install /usr/bin/install -c watchman '//usr/local/bin'
libtool: install: /usr/bin/install -c watchman //usr/local/bin/watchman
/usr/bin/install -c -d -m 777 //usr/local/var/run/watchman
chmod g+s //usr/local/var/run/watchman
touch //usr/local/var/run/watchman/.not-empty
 ./install-sh -c -d '//usr/local/share/doc/watchman-4.9.0'
 /usr/bin/install -c -m 644 README.markdown '//usr/local/share/doc/watchman-4.9.0'
make[1]: Leaving directory '/usr/src/app/watchman'

できたのかな…?

watchmanってrootで打ってみた。

{
    "cli_validated": true,
    "version": "4.9.0",
    "error": "invalid command (expected an array with some elements!)"
}

イケてるっぽい

.gitignorewatchmanを追加しました。

windowsへdocker-windows-volume-watcherを導入

GAE/GOなdockerを作ろうとしたら10時間溶けた
↑を参考にしました。

windowsのコマンドプロンプトで

pip install --upgrade pip
pip install docker-windows-volume-watcher
docker-volume-watcher
PS D:\ok\プログラミング学習\React-TextEditer> docker-volume-watcher
WARNING:root:Bind of container react-textediter_react_native_1 was skipped since it has invalid source path D:\ok\プログラミング学習\React-TextEditer\react_native
WARNING:root:No mounts match container name pattern * and host directory pattern *

ちーん(´;ω;`)

WARNING:root:Bind of container was skipped since it has invalid source path

dockerDesktopのせいなのかな…

rootの名前をReact-TextEditerからReact_TextEditerに変更

ドッカ―イメージからビルドしなおします。

docker-volume-watcher

だめでしたー!
名前の問題ではないみたい。

ってか、日本語PATHがダメなのではなかろうか…
と思ってプログラミング学習を英語に変えたけどダメでした。
こまったな~!

pip uninstall docker-windows-volume-watcher

zippoxer/docker-windows-volume-watcher
↑こっちも使ってみたいけど、インストールの仕方が分からず💦

kerbe/expoでコンテナ作成・実機確認

kerbe/expo

こちらを使っていきたいと思います!

kerbe/docker-expoを参考にDockerfileとdocker-compose.ymlを編集

FROM kerbe/expo

WORKDIR /usr/src/app
version: "3"
services:
  react_native:
    build: ./docker/react_native
    volumes:
      - ./react_native:/usr/src/app
    env_file: .env

    command: start

    ports:
      - "19000:19000"
      - "19001:19001"
      - "19002:19002"
      - "19006:19006"

react_nativeディレクトリを削除して、以下を実行しました。

docker-compose build
docker-compose run --rm react_native init .

templateをblanckと入力。
終わったら、docker-compose upします。

よくわからなかったので、ファイルの編集とコマンドの編集を何度もチャレンジしましたw

成功!
とりあえず、実機確認までできました。

ホットリロードができるか問題

CHOKIDAR_USEPOLLING=trueを設定しているので、webブラウザでは一応リロードしてくれます。
iPhoneではホットリロードが効いていません。
merofeev/docker-windows-volume-watcher
これが使えないので、
zippoxer/docker-windows-volume-watcher
こっちを使ってみることにしました。

goをインストール

WindowsにGo言語開発環境をインストールする
↑こちらの手順にしたがって、Goをインストールしました。

How can I install a package with go get?
↑ go getしたらいけるっぽい
Windowsのコマンドプロンプトから、go get github.com/zippoxer/docker-windows-volume-watcherをします。

go get: github.com/zippoxer/docker-windows-volume-watcher@none updating to
        github.com/zippoxer/docker-windows-volume-watcher@v0.0.0-20190226212435-676f3ba5696c: parsing go.mod:
        module declares its path as: github.com/FrodeHus/docker-windows-volume-watcher
                but was required as: github.com/zippoxer/docker-windows-volume-watcher

とのことなので、go get github.com/FrodeHus/docker-windows-volume-watcherしてみます。

docker-windows-volume-watcher -container=[react_textediter_react_native_1]

↑をWindowsのコマンドプロンプトから作業ディレクトリに移動してうってみると、いけてる感じがします!

試しにファイルを変更してみると…↓

Updating container file react_native/App.js
Error notifying container about file change: exit status 1
Updating container file react_native/.expo/web/cache/development/babel-loader/7c5042ec877f84a9db21a9f6f73ac149.json
Error notifying container about file change: exit status 1

もうだめだ!\(^o^)/オワタ

ホットリロードは諦めます。

そもそもDocker使わない方がいい気しかしないので、明日は違う方法検討しよう!

時間かかるので辞めましたw

↓続き
【4】React Nativeでテキストエディタを作ってみる!【再び環境構築編】【4】React Nativeでテキストエディタを作ってみる!【再び環境構築編】

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です