自動化無しに生活無し

WEB開発関係を中心に備忘録をまとめています

よく出るReactのエラー一覧

thumbnail

textarea要素には、valueプロパティを使って値を与える

普通のHTMLでは、textareaに最初から値を入れておきたい場合、子要素に直接文字を書くと良い。

しかし、Reactで同じことをやるとエラーになる。

<textarea className="form-control" name="comment" onChange={this.handleChange}>{this.state.activeItem.comment}</textarea>

そこで、valueプロパティを使う。

<textarea className="form-control" name="comment" onChange={this.handleChange} value={this.state.activeItem.comment}></textarea>

これで、

Use the `defaultValue` or `value` props instead of setting children on <textarea>.

というエラーは解決される。

リスト内の要素を識別できるよう、keyプロパティを与える

Each child in a list should have a unique "key" prop. 

リストをレンダリングする時。

renderItems = () => {
    return this.state.topicList.map((item) => (
        <div className="border">
            <div>{item.id}:{item.comment}</div>
            <textarea className="form-control" name="comment" value={item.comment} onChange={this.handleChange}></textarea>
            <div className="text-end">
                <input type="button" className="btn btn-danger" value="削除" onClick={() => this.handleDelete(item)} />
            </div>
        </div>
    ));
};

このように、レンダリングする要素が識別できない時、エラーが出る。

keyプロパティを与えてレンダリングをする。

renderItems = () => {
    return this.state.topicList.map((item) => (
        <div className="border" key={item.id}>
            <div>{item.id}:{item.comment}</div>
            <textarea className="form-control" name="comment" value={item.comment} onChange={this.handleChange}></textarea>
            <div className="text-end">
                <input type="button" className="btn btn-danger" value="削除" onClick={() => this.handleDelete(item)} />
            </div>
        </div>
    ));
};

参照: 【React】リストをレンダリングする時は、key属性を付与する【Warning: Each child in a list should have a unique ‘key’ prop.】

閉じタグがないHTMLは、タグの末尾に / をつける。

<input type="button" onClick={handleClick} value="送信">

こう書いた場合、エラーになる。

<input type="button" onClick={handleClick} value="送信" />

このようにタグの末尾に / を入れる。

参照: 【React】閉じタグがないHTML要素は/(スラッシュ)をタグの末尾に書く【inputタグ、imgタグ等】

on属性に与える関数を、()つきにすると無限ループする。

<button onClick={handleClick()}>クリックしてください</button>

例えば、このようにしてしまうと、handleClickはクリックされなくても実行され続ける。

<button onClick={handleClick}>クリックしてください</button>

このように() をつけず、関数名のみ指定する。

関数呼び出し時に引数を与えるには、無名関数でラップする。

<button onClick={ (event) => { handleClick(event.currentTarget.value) } } value="値">クリックしてください</button>

参照型

例えば、Stateがオブジェクトや配列の場合、

このようにsetStateをしても、再レンダリングされることはない。

    // 前提: todosは { 1: { ... }, 2: {...}, 3: {...} } となっている。

    const toggleIsEditing = (id) => {
        console.log( todos[id] );

        todos[id].is_editing = !todos[id].is_editing;
        setTodos(todos);
    }

このようにオブジェクトの値を書き換えても、ReactはState(オブジェクト)の変化を検知できないため、再レンダリングは発動しない。

もし、オブジェクトの値を書き換え、再レンダリングをさせるには、こうする。

    const toggleIsEditing = (id) => {
        setTodos((prevTodos) => {
            const updatedTodos  = { ...prevTodos };
            updatedTodos[id]    = { ...updatedTodos[id], is_editing: !updatedTodos[id].is_editing };
            return updatedTodos;
        });
    };

setTodos を関数として実行。

todosをprevTodos として扱い、値を書き換えreturn する。

この時、スプレッド構文を使ってオブジェクトをコピーする。間違っても

const updatedTodos = prevTodos;

としてはいけない。この場合は参照値が引き継がれてしまう。

オブジェクトのコピーをして編集するときは、スプレッド構文は厳守する。

スポンサーリンク