RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-04-30中級

RorkアプリのTextInputで文字が消える・カーソルが飛ぶ問題を3パターンで直す

Rorkで生成したアプリのTextInputで、入力中に文字が消えたりカーソルが文末に飛んだりする問題を、再レンダリング・親stateの遅延・onChangeText変換の3パターンで切り分けて直す方法を解説します。

Rork515TextInput2React Native209トラブルシューティング77状態管理11

「Rorkで作ったアプリのTextInputに文字を入力していると、たまに1文字消えたり、カーソルが勝手に文末に飛んだりする」— この症状、開発者の手元では再現しにくいくせに、本番のユーザーレビューには確実に響く厄介な現象です。私もRorkで最初の数本を作っていたころ、ストアのレビューで「文字入力で1文字飛ぶ」という指摘をもらって、ようやく自分のコードの問題に気づきました。

「動いているように見えるのに、なぜかユーザーが気持ち悪がる」状態から抜け出すための実践的なチェックリストとして使ってください。

なぜTextInputで文字が消えたりカーソルが飛んだりするのか

React NativeのTextInputは、入力された1文字ごとにonChangeTextが呼ばれ、useStateで値を保持し、次のレンダリングでvalueプロパティとして書き戻す、という流れで動いています。この一連の流れのどこかで遅延・ループ・上書きが発生すると、ユーザーから見て「打った文字が消える」「カーソルが文末にワープする」といった症状になります。

特に厄介なのは、英語入力ではほとんど顕在化しないのに、日本語IMEや予測変換が走る環境でだけ症状が出るケースです。Rorkは英語圏のユーザーを想定したコードを生成することが多いため、生成直後のコードを何も考えずに本番投入すると、日本語ユーザーから不具合報告を受ける確率が高くなります。

これから紹介する3パターンは、いずれも「入力 → state更新 → 再レンダリング → value書き戻し」のサイクルが何らかの理由で乱れることが共通の原因です。順に見ていきましょう。

パターン1: 派生state を別変数で持って毎回再レンダリングしている

最も多いのは、TextInputを含む画面が、別のstateの更新によって毎キーストロークで余計に再レンダリングされているパターンです。

// ❌ 悪い例 — setText と setCount で再レンダリングが2回走り、
//   IMEの未確定状態を巻き込んで1文字消えることがある
function NoteEditor() {
  const [text, setText] = useState('');
  const [count, setCount] = useState(0);
 
  return (
    <View>
      <Text>文字数: {count} / 200</Text>
      <TextInput
        value={text}
        onChangeText={(t) => {
          setText(t);
          setCount(t.length); // ← この2回目の更新が問題
        }}
        multiline
      />
    </View>
  );
}

このコードの問題は、setTextsetCountを続けて呼んでいる点です。Reactは通常これらをバッチ処理するのですが、IMEの未確定文字を挟んだ状態だと、まれに2回目の更新が「直前の入力をなかったこと」にしてしまいます。Rorkに「文字数カウンター付きのテキストエリアを作って」と頼むと、このパターンを書いてくることが少なくありません。

// ✅ 正しい書き方 — stateは1つに集約、派生値はレンダリング時に計算する
function NoteEditor() {
  const [text, setText] = useState('');
 
  return (
    <View>
      <Text>文字数: {text.length} / 200</Text>
      <TextInput
        value={text}
        onChangeText={setText}
        multiline
      />
    </View>
  );
}

派生値(文字数・残り文字数・バリデーション結果など)は別のstateで持たず、レンダリング時に直接計算するか、必要ならuseMemoで導出するのが鉄則です。「state は信号、派生値は配線」と覚えておくと、無駄な再レンダリングを避けられます。

パターン2: 親から渡される value が遅れて入力を上書きする

2つ目は、TextInputが親コンポーネントからvalueを受け取っていて、その親側の更新が遅れてキー入力を上書きしてしまうパターンです。

// ❌ 悪い例 — onChangeText 内でAPI保存を await している
function ProfileForm({ initialName, onSave }: Props) {
  const [name, setName] = useState(initialName);
 
  const handleChange = async (t: string) => {
    setName(t);
    await onSave(t); // ← API保存の完了後に古い値が書き戻される
  };
 
  return <TextInput value={name} onChangeText={handleChange} />;
}

ユーザーが「あいうえお」と入力している最中に、サーバー保存の完了で「あいう」がvalueに書き戻されると、その後に打った「えお」が消えたように見えます。日本語IMEの確定タイミングと重なると、未確定文字ごと消失することもあります。

// ✅ 正しい書き方 — 入力反映と保存処理を分離し、500ms のデバウンスをかける
function ProfileForm({ initialName, onSave }: Props) {
  const [name, setName] = useState(initialName);
 
  useEffect(() => {
    const id = setTimeout(() => {
      if (name !== initialName) onSave(name);
    }, 500);
    return () => clearTimeout(id);
  }, [name]);
 
  return <TextInput value={name} onChangeText={setName} />;
}

入力UIの責務は「入力を受け付けてローカルstateに反映する」ことだけにし、保存処理は別レイヤーに切り出す — これは制御コンポーネント全般に通じる設計原則です。

パターン3: onChangeText 内でテキストを変換してループを作る

3つ目はパターン1・2に比べて遭遇率は低いものの、原因がわかりにくく、踏むと半日溶けます。onChangeText内で渡されたテキストを変換してからsetTextするパターンです。

// ❌ 悪い例 — 入力のたびに大文字変換、IMEの未確定文字も大文字化される
<TextInput
  value={text}
  onChangeText={(t) => setText(t.toUpperCase())}
/>

英語入力では問題なく動くのですが、日本語IMEで「あ」を打って変換中の状態に対してtoUpperCase()を毎キーストローク適用すると、IMEバッファが壊れて変換候補が消える、未確定文字がローマ字のまま確定する、といった症状になります。先頭を自動で大文字化するUIや、半角カナを全角に強制変換するUIで特に発生しやすい落とし穴です。

// ✅ 正しい書き方 — 変換は確定後(onEndEditing or onBlur)に行う
<TextInput
  value={text}
  onChangeText={setText}
  onEndEditing={(e) => setText(e.nativeEvent.text.toUpperCase())}
/>

入力中のテキストには手を加えず、IMEが文字を確定したタイミング(onEndEditingonBlur、または送信ボタンのハンドラ内)で変換処理を入れるのが鉄則です。「入力中のリアルタイム整形は基本的に悪手」と覚えておくと、似たバグを未然に防げます。

デバッグの順序 — まず何を疑うべきか

実際に手元のRorkアプリでTextInputの入力不具合に遭遇したら、私はいつもこの順序で切り分けます。

  • まずTextInputを含む画面の関数の冒頭にconsole.log('render');を入れて、1キー入力で何回再レンダリングされるかを数える。3回以上ならパターン1の疑いが濃厚です
  • 次に親からvalueが渡されている場合、その親側の更新ロジックに非同期処理(awaituseEffect内のfetchなど)がないかを確認します。あればパターン2を疑います
  • それでも直らなければ、onChangeTextの中身を一時的にsetText(t)だけに減らし、症状が消えるかを確認します。消えたらパターン3です

再現環境は「iOSの実機 × 標準IME × 日本語キーボード」で固定するのが最短ルートです。シミュレーターの英語キーボードでは多くの場合再現せず、Androidエミュレーターも入力レイテンシの違いで挙動が変わるため、実機テストの工程を省略しないことをおすすめします。

締めくくり

TextInputの入力不具合は、開発者の手元では再現しにくいくせに、ユーザーレビューには確実に響く領域です。Rorkは多くの場合うまく書いてくれますが、stateの分割や非同期処理を後から追加していくうちに、3つのパターンのいずれかに陥ることがあります。

直す順番は決まっていて、再レンダリング → 親stateの遅延 → onChangeText内の変換、の3つを上から順に疑うだけ。1つずつ可能性を消していけば、ほぼ確実に発生源にたどり着けます。次にRorkでアプリを作るときは、TextInputの実装が終わった段階で一度だけ日本語の実機テストを挟んでみてください。リリース後にレビューで気づくよりも、はるかに少ないコストで品質が上がるはずです。同じ系統の問題として、IME変換中のイベント暴発に手を焼いている方は、Rorkアプリの日本語入力が「変換中に暴発する」問題も併せて読むと、引き出しが増えると思います。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-04-22
Rorkで作ったアプリの日本語入力が『変換中に暴発する』問題を根本解決する
Rorkで生成したアプリの日本語入力で、IMEの変換中にイベントが暴発する・候補ウィンドウが閉じる問題の原因と対処法を、実際に動くコードと合わせて解説します。
開発ツール2026-07-14
AI再生成に壊されない設計 — Rork の生成コードと手書きロジックを分ける境界の引き方
Rork へ追加指示を出すたびに手書きのロジックが消える。プロンプトで守るのは対症療法です。生成コードと自分の所有コードを層で分け、再生成が届かない境界を設計で引く方法を、Zustand と service 層の実装例つきでお伝えします。
開発ツール2026-06-21
Rork のお気に入り一覧を長押しドラッグで並べ替える — 再レンダリングを抑えた reorderable list と並び順の永続化
Rork が生成したお気に入り一覧に、長押しドラッグの並べ替えを後から足す実装手順です。再レンダリングを抑える設計、worklet の境界、並び順の永続化、ジャンクやゴーストカードの回避までを実コードでまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →