質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

5591閲覧

stateで管理している配列要素の追加と削除の方法を知りたい

tomaa

総合スコア84

React Native

React Nativeは、ネイティブモバイルアプリ(iOS/Android)を作成できるJavaScriptフレームワークです。Reactと同じ設計のため、宣言的なコンポーネントでリッチなUIを開発することが可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/08/08 09:48

編集2020/08/09 16:43

前提・実現したいこと

React Nativeを利用してアプリの開発をしています。

Stateで配列([])を管理する際の、要素の追加と削除の方法を知りたいです。

const [name, setName] = useState([]);
と宣言した場合、
setNameを使って、追加、削除したほうが良いと思うのですが、どのようにすればよいかわかりません。

例えば、
const [name, setName] = useState([""]);
というように初期値を設定してから、
setName(name.push(""));
と行うと、配列の要素が増えずになぜか「2」が値として入ります。

方法をご存知の方おりましたら、ご教授いただけないでしょうか?

今質問の背景

もともと、連想配列でテキストの入力を含むコンポーネントの追加、削除を行う予定でした。

しかし、下記の画像のような削除の仕方をしたい時に、通常の配列([])を利用したほうが、コードを作りやすいと思い現在改良をしています。
イメージ説明

該当のソースコード

連想配列を利用した場合のコード

JS

1import React, { useState } from "react"; 2import { View, Button, Text, TextInput } from "react-native"; 3 4function Item({ setText, handleAdd, i }) { 5 return ( 6 <View> 7 <TextInput 8 style={{ borderWidth: 1 }} 9 onChange={(e) => { 10 setText(i, e.nativeEvent.text); 11 }} 12 ></TextInput> 13 <Button 14 title="追加" 15 onPress={() => { 16 handleAdd(); 17 }} 18 ></Button> 19 </View> 20 ); 21} 22 23export default function TestStateArray() { 24 const [count, setCount] = useState(1); 25 const [name, setName] = useState({}); 26 27 function handleAdd() { 28 setCount((v) => v + 1); 29 } 30 return ( 31 <View> 32 <Text>確認{JSON.stringify(name)}</Text> 33 {Array.from({ length: count }, (_, i) => ( 34 <Item 35 handleAdd={handleAdd} 36 setText={(i, text) => setName((prev) => ({ ...prev, [i]: text }))} 37 key={i} 38 i={i} 39 /> 40 ))} 41 </View> 42 ); 43} 44

通常の配列でのコード

JS

1import React, { useState, useEffect } from "react"; 2import { View, Text, Button, TextInput } from "react-native"; 3 4function Item({ setName, handleAdd, handleDelete, index }) { 5 return ( 6 <View> 7 <TextInput 8 style={{ borderWidth: 1 }} 9 onChange={(e) => { 10 setName(e.nativeEvent.text); 11 }} 12 ></TextInput> 13 <Button 14 title="追加" 15 onPress={() => { 16 handleAdd(); 17 }} 18 /> 19 <Button 20 title="削除" 21 onPress={() => { 22 handleDelete(index); 23 }} 24 /> 25 </View> 26 ); 27} 28 29export default function TestStateArray() { 30 const [count, setCount] = useState(1); 31 const [name, setName] = useState([""]); 32 33 function handleAdd() { 34 setCount((v) => v + 1); 35 setName(name.push("")); 36 } 37 function handleDelete(index) { 38 setCount((v) => v - 1); 39 setName(name.splice(index, 1)); 40 } 41 console.log(name); 42 return ( 43 <View> 44 <Text>確認{JSON.stringify(name)}</Text> 45 46 {Array.from({ length: count }, (_, i) => ( 47 <Item 48 name={name} 49 setName={setName} 50 handleAdd={handleAdd} 51 handleDelete={handleDelete} 52 key={i} 53 index={i} 54 /> 55 ))} 56 </View> 57 ); 58}

補足情報(FW/ツールのバージョンなど)

node : 12.18.3
react native : 4.10.1
expo : 3.22.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

setName(name.push(""));

と行うと、配列の要素が増えずになぜか「2」が値として入ります。

これはsetNameに渡しているのがname.push("")の戻り値だからです。
Array.prototype.push()は下記のリファレンスにあるようにpush後のlengthが戻り値になります。

stateで管理している配列を扱う場合は、単純に更新したい内容の配列を渡すだけです(先の例ではname.push("")した後の配列)。
ただ、state中の配列を扱うには、stateから取得したばかりの配列にsplice()push()等の破壊的な変更を伴うメソッドを使ってはいけません。
これはReactstateの変更をObject.is()で判定していることに起因します。
詳しくは、下記記事で解説がありました。

具体的にどうすればいいかというと、新しい配列に入れ直してからsetNameを実行する必要があります。
方法は色々ありますが、スプレッド演算子...あたりを使うのがベターかと思います。

javascript

1const [name, setName] = useState([]); 2 3// 下記はNG 4// name.push("hoge"); 5// setName(name); 6 7// 下記はOK 8const newName = [...name, "hoge"]; 9setName(newName);

投稿2020/08/10 10:36

nekoniki

総合スコア2411

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomaa

2020/08/10 10:55

ご回答いただきありがとうございます。 詳しく解説していただき、大変わかりやすいです。 具体的な対策も示していただきありがとうございます。 非常に参考になりました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問