如何将 map 函数用于钩子 useState 属性

IT技术 reactjs react-hooks
2021-05-19 16:29:06

我尝试使用 map 函数在 react-hooks useState 中循环我的列表数据,但我遇到了一个错误“TypeError:无法读取未定义的属性‘map’”

//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)
}))}

在此处输入图片说明

2个回答

正如我们怀疑您没有以正确的方式设置您的状态。我试图在我的评论中解释,当您设置状态时,使用钩子不会将更新的属性与当前的属性合并。所以,你应该考虑一下。现在你正在像这样设置你的状态:

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,
  }));
};

此外,您的代码中还有一些其他问题和不必要的部分。例如,您在处理提交和向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"));

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

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