0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ReactでObjectを受け取ってのObjectのstateを変更したい

Posted at

タイトルそのままです。

index.js
const initialState = {
   'user1': true,
   'user2': true,
    ...
};
const [user, setUser] = React.useState(initialState);

というようなstateがあったとして、例えばクリックされたユーザ番号のvalueを変えたいとします。で、すべてにチェックをチェックしたら、全チェックボックスがチェックされるようにしたい。
なので、1個チェックしたときは、Object内のチェックしたkey, valueペアだけ返してstateを変更し、全チェックしたときは、すべてのObject内のkeyに対してvalueだけ変更してObjectを丸々返すようにしたかったのですが、Objectを丸々受け取ってそれをReactのstateに渡すにはどうしたらよいのかが地味にわからなくて時間がかかりました。

Codesandboxはこちら

User.js
export default function User({ users, handleChange }) {
  function getUserObject(users, key, value) {
    if (key === null && value === null) {
      Object.entries(users).map(([key, val]) => {
        users[key] = !val;
      });
      return users;
    }
    return { [key]: !value };
  }
  return (
    <>
      <input
        type="checkbox"
        onChange={() => handleChange(getUserObject(users, null, null))}
      />
      <label>check all</label>
      {users ? (
        Object.entries(users).map(([key, value]) => {
          return (
            <div>
              <input
                type="checkbox"
                checked={value}
                onChange={() => handleChange(getUserObject(users, key, value))}
              />
              <label>{key}</label>
            </div>
          );
        })
      ) : null}
    </>
  );
}
App.js
export default function App() {
  const initialState = {
    user1: false,
    user2: false
  };
  const [users, setUser] = React.useState(initialState);

  return (
    <div className="App">
      <User
        users={users}
        handleChange={(obj) =>
          setUser((state) => Object.assign({ ...state }, obj))
        }
      />
    </div>
  );
}

ポイント1: Object.assignならObjectそのままを渡せる

ポイントはここです。Object.assignを使い、さらにstate...stateではなくて、{...state}で渡す必要があります。ちなみにObjectを変更するやり方は色々あって、Object.assignでなくても{...state, key: val}でも行けるようですが、そうすると、Objectはそのまま渡せません。

index.js
setUser((state) => Object.assign({ ...state }, obj))

ポイント2: key, valueを変数名で受け取ってObjectにしたい

全てのkey, valueに対してvalueの値を変更したい場合はこう。

index.js
Object.entries(users).map(([key, val]) => {
        users[key] = !val;
});

一個のkey, valueペアについて単体でObjectを作って返したいとき。

こうする。ミソは[key]ここ。 key: !valueだと、key名がそのままkeyという名前のObjectになってしまいます...ので、[key]にしないと認識されません。

index.js
{ [key]: !value };

コード例自体は別のところで使用したものをこれを書くためにサクッと書いたので、まあちょっとおかしなところありますが...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?