如何将映射函数用于挂钩 useState 属性

How to use map function for hooks useState properties

我尝试使用 map 函数在 react-hooks useState 中循环我的列表数据,但我遇到了一个错误 "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)
}))}

如果您的列表为空,您将收到此错误,只需检查列表是否为空即可解决问题:

{if(state.list){
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,
  }));
};

你取旧状态,spreading保留其他属性,然后更新相关部分。我会在这里使用 event 而不是 name。它不是 "name",它实际上是 "event":)

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

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

此外,您的代码中还有其他一些问题和不必要的部分。例如,您正在努力处理提交并将对象添加到您的 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"));