1. ホーム
  2. reactjs

[解決済み] useStateプロパティのフックにmap関数を使用する方法

2022-02-05 14:03:59

質問

react-hooks useStateでリストデータをループさせるためにmap関数を使おうとしましたが、 "TypeError.というエラーで止まってしまいました。Cannot read property 'map' of undefined".と表示されます。

//1.Initial declaration
const App = props=>  {
const [state, changeState]= useState ({
    name:"",
    eventTitle:"",
    details:"",
    objdata:{},
    list:[],
    toggleIndex:"",
    editName: "",
    editEventTitle: "",
    editDetails: "",
    editObj: {}
});


//2.logic comes here


//3.tried using map


{(state.list.map((data,id)=>{
console.log ('loop data',data)
}))}

解決方法は?

推測されるように、あなたは正しい方法で状態を設定していません。コメントで説明したように、フックを使って状態を設定すると、更新されたプロパティが現在のプロパティにマージされません。だから、あなたはそのことについて考える必要があります。今、あなたはそのように状態を設定しています。

const handleName = name => {
  changeState({
    name: name.target.value
  });
};

ここでは name プロパティを使用すると、ステートの他の部分を失うことになります。したがって状態を設定すると list というように、他の部分と同じように、自分の状態を表すことができます。このようにすればいいのです。

const handleName = name => {
  const { target } = name;

  changeState(state => ({
    ...state,
    name: target.value,
  }));
};

で古い状態を取り、他のプロパティを維持するのです。 拡散 を作成し、該当箇所を更新します。私なら、ここで event の代わりに name . 結局のところ、名前ではなく、イベントなのです。)

const handleName = event => {
  const { target } = event;

  changeState(state => ({
    ...state,
    name: target.value,
  }));
};

また、あなたのコードには、他にもいくつかの問題や不要な部分があります。例えば、submitを処理するのに苦労しすぎて、オブジェクトを list . を追加する必要はありません。 objdata にプッシュするために、あなたのステートで list . もし余分なオブジェクトを構築したい場合は、関数自体の中で行うことができます。

ここでは、非常に簡単な方法を紹介します。

const submitHandle = () => {
  const { name, eventTitle, details } = state;
  const obj = { name, eventTitle, details };

  changeState(state => ({
    ...state,
    list: [ ...state.list, obj ],
  }))
};

ここでも、スプレッド演算子を使って、状態の他の部分と、更新中の list 他のオブジェクトを保持するためです。のように状態を設定しないでください。 submitHandle 関数を使用します。シンプルに考えてみてください :)

また、必要でない場合は関数をバインドする必要はありません。以下に動作するコードのコピーを掲載します。不要な部分を削除し、問題点を修正しただけです。

import React, { useState } from "react";
import ReactDOM from "react-dom";

const App = props => {
  const [state, changeState] = useState({
    name: "",
    eventTitle: "",
    details: "",
    list: [],
    toggleIndex: "",
    editName: "",
    editEventTitle: "",
    editDetails: "",
    editObj: {}
  });

  const handleName = event => {
    const { target } = event;

    changeState(state => ({
      ...state,
      name: target.value
    }));
  };

  const handleEventTitle = event => {
    const { target } = event;

    changeState(state => ({
      ...state,
      eventTitle: target.value
    }));
  };

  const handleDetails = event => {
    const { target } = event;

    changeState(state => ({
      ...state,
      details: target.value
    }));
  };

  const submitHandle = () => {
    const { name, eventTitle, details } = state;
    const obj = { name, eventTitle, details };

    changeState(state => ({
      ...state,
      list: [...state.list, obj]
    }));
  };

  const resetHandle = () =>
    changeState(state => ({
      ...state,
      name: "",
      eventTitle: "",
      details: ""
    }));

  return (
    <div>
      <div className="jumbotron jumbotron-fluid">
        <div className="container">
          <h1 className="display-5 text-center">Let's set your reminders</h1>
        </div>
      </div>
      <div className="bg-dark container-fluid">
        <div className="row">
          <div className="col-sm-12 col-md-4 col-lg-4 " />

          <div className="col-sm-12 col-md-4 col-lg-4 ">
            <div className="card login-card ">
              <div className=" card-header ">
                <h3 className="text-center"> TO-DO LIST FORM</h3>
              </div>

              <div className="card-body">
                <form className="form-elements">
                  <input
                    value={state.name}
                    className="form-control form-inputs form-elements"
                    type="text"
                    onChange={handleName}
                    placeholder="user name"
                  />
                  <input
                    value={state.eventTitle}
                    className="form-control form-inputs form-elements"
                    type="text"
                    onChange={handleEventTitle}
                    placeholder="Event Title"
                  />
                  <input
                    value={state.details}
                    className="form-control form-inputs form-elements"
                    type="text"
                    onChange={handleDetails}
                    placeholder="Details "
                  />
                </form>
              </div>

              <div className="card-footer ">
                <button
                  type="submit"
                  onClick={submitHandle}
                  className="btn-primary offset-lg-1 offset-md-0 btn-sm "
                >
                  Create
                </button>

                <button
                  type="reset"
                  onClick={resetHandle}
                  className="btn-primary offset-lg-5 offset-md-0 btn-sm"
                >
                  cancel
                </button>
              </div>
            </div>
          </div>
          <div className="col-sm-12 col-md-4 col-lg-4 " />
        </div>

        <div className="container-fluid bg-dark">
          <div className="row ">
            {state.list.map(data => (
              <div style={{ border: "1px black solid" }}>
                <p>{data.name}</p>
                <p>{data.eventTitle}</p>
                <p>{data.details}</p>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div
        className="footer footer-copyright"
        style={{ background: "#e9ecef" }}
      >
        <div className="container">
          <h6 className=" text-center">Just make it work ;)</h6>
        </div>
      </div>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));