【问题标题】:TypeError: Cannot read property 'map' of undefined is showing when I'm trying to map over the props passed from parent component to child componentTypeError: Cannot read property 'map' of undefined 在我尝试映射从父组件传递到子组件的道具时显示
【发布时间】:2021-05-24 06:38:24
【问题描述】:

我在从父组件 (App.js) 到子组件 (Label.js) 的传递道具上映射时遇到问题。终端向我显示编译成功并带有警告。当我在我的应用程序中单击登录按钮时,我直接收到一条警报:“无法读取未定义的属性 'map'”,单击确定后,显示此错误:“TypeError: Cannot read property 'map' of undefined is显示我何时尝试映射从父组件传递到子组件的道具”。我是 React 钩子的新手,非常感谢任何帮助,请原谅长行代码。 谢谢

App.js

import Label from "./Label";
import Register from "./Registration";

export default function App() {
  const [add_task_data, setAddTaskData] = useState({
    title: "",
    description: "",
    date: "",
    priority: "",
  });

  const [state, setState] = useState({
    isAuthenticated: false,
  });
  const [login, setLogin] = useState({
    email: "",
    password: "",
  });


  const [todos, setTodos] = useState([]);

  const fetchTodos = () => {
    if (state.isAuthenticated) {
      var myHeaders = new Headers();
      myHeaders.append("Accept", "application/json");
      myHeaders.append(
        "Authorization",
        `Bearer ${localStorage.getItem("access_token")}`
      );

      var requestOptions = {
        method: "GET",
        headers: myHeaders,
        redirect: "follow",
      };

      fetch("https://codeminos-todo.tk/api/v1/to-dos", requestOptions)
        .then((response) => response.text())
        .then((json) => {
          const result = JSON.parse(json);
          setTodos(result.data);
        })
        .catch((error) => console.log("error", error));
    }
  };
  
  // const checkUserAuth = () => {
    if (state.isAuthenticated) {
      var myHeaders = new Headers();
      myHeaders.append("Accept", "application/json");
      myHeaders.append(
        "Authorization",
        `Bearer ${localStorage.getItem("access_token")}`
      );

      var requestOptions = {
        method: "GET",
        headers: myHeaders,
        redirect: "follow",
      };

      fetch("https://codeminos-todo.tk/api/v1/labels", requestOptions)
        .then((response) => response.text())
        .then((json) => {
          setState({
            isAuthenticated: true,
          });
        })
        .catch((error) => {
          setState({
            isAuthenticated: false,
          });
        });
    }
  // };

  // const fetchLabels = () => {
  //   if (state.isAuthenticated) {
  //     var myHeaders = new Headers();
  //     myHeaders.append("Accept", "application/json");
  //     myHeaders.append(
  //       "Authorization",
  //       `Bearer ${localStorage.getItem("access_token")}`
  //     );

  //     var requestOptions = {
  //       method: "GET",
  //       headers: myHeaders,
  //       redirect: "follow",
  //     };


  //   }
  // };
  
  // useEffect(() => {
  //   fetchTodos();
  //   // fetchLabels();
  // }, [state.isAuthenticated]);
  
  function handleChange(key, value) {
    setAddTaskData({
      ...add_task_data,
      [key]: value,
    });
  }
  function hanldeLoginChange(key, value) {
    setLogin({
      ...login,
      [key]: value,
    });
  }
  const handleLoginSubmit = (event) => {
    event.preventDefault();
    var myHeaders = new Headers();
    myHeaders.append("Accept", "application/json");
    myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

    var urlencoded = new URLSearchParams();
    urlencoded.append("email", "pas2ss@gmail.com2");
    urlencoded.append("password", "212312322");

    var requestOptions = {
      method: "POST",
      headers: myHeaders,
      body: urlencoded,
    };

    fetch("https://codeminos-todo.tk/api/login",requestOptions) 
     
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        if (data.access_token !== undefined) {
          localStorage.setItem("access_token", data.access_token);
          setState({
            ...state,
            isAuthenticated: true,
          });
        }
      })
      .catch((error) => {
        alert(error.message);
      });
  };

  const handleAddToDoSubmit = (event) => {
    event.preventDefault();
    var myHeaders = new Headers();
    myHeaders.append("Accept", "application/json");
    myHeaders.append(
      "Authorization",
      `Bearer ${localStorage.getItem("access_token")}`
    );
    myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

    var urlencoded = new URLSearchParams();
    urlencoded.append("title", add_task_data.title);
    urlencoded.append("description", add_task_data.description);
    urlencoded.append("priority", add_task_data.priority);
    urlencoded.append("date", add_task_data.date);

    var requestOptions = {
      method: "POST",
      headers: myHeaders,
      body: urlencoded,
      redirect: "follow",
    };

    fetch("https://codeminos-todo.tk/api/v1/to-dos", requestOptions)
      .then((response) => response.text())
      .then((result) => {
        fetchTodos();
      })
      .catch((error) => console.log("error", error));
  };
  
  
  return (
    <>
      <div>
        <Register /> <br/>
        
        <br/>
      </div>
      <div className="App">
        <h2>Welcome to your task manager app</h2>

        {!state.isAuthenticated && (
          <div>
            <h2>You are not authenticated, please login</h2>

            <form onSubmit={(event) => handleLoginSubmit(event)}>
              <div>
                <label>Email: </label>
                <input
                  type="text"
                  name="email"
                  onChange={(event) => {
                    hanldeLoginChange("email", event.target.value);
                  }}
                />
              </div>
              <div>
                <label>password</label>

                <input
                  type="text"
                  name="password"
                  onChange={(event) => {
                    hanldeLoginChange("password", event.target.value);
                  }}
                />
              </div>
              <input type="submit" value="login" />
            </form>
          </div>
        )}
        {state.isAuthenticated && (
          <div>
            <h2>Tasks</h2>
            {todos.map((todo) => {
              return (
                <div>
                  Title {todo.title} --- description: {todo.description}
                </div>
              );
            })}

            
            <button
              onClick={() => {
                setState({
                  ...state,
                  isAuthenticated: false,
                });
                localStorage.removeItem("access_token");
              }}
            >
              Logout
            </button>
            <h2>Add TODO</h2>
            <form
              onSubmit={(event) => {
                handleAddToDoSubmit(event);
              }}
            >
              <div>
                <label>Title</label>
                <input
                  type="text"
                  name="title"
                  onChange={(event) => {
                    handleChange("title", event.target.value);
                  }}
                />
              </div>
              <div>
                <label>description</label>

                <input
                  type="text"
                  name="description"
                  onChange={(event) => {
                    handleChange("description", event.target.value);
                  }}
                />
              </div>
              <div>
                <label>date</label>

                <input
                  type="text"
                  name="date"
                  onChange={(event) => {
                    handleChange("date", event.target.value);
                  }}
                />
              </div>
              <div>
                <label>priority</label>
                <input
                  type="text"
                  name="priority"
                  onChange={(event) => {
                    handleChange("priority", event.target.value);
                  }}
                />
              </div>
              
              <Label {...add_task_data.title}/>
              
              <input type="submit" value="add todo" />
            </form>
            {JSON.stringify(add_task_data)}
          </div>
        )}
      </div>
    </>
  );
}

标签.js


export default function Label(props){
  const [labels, setLabels] = useState({ label: "" });
   const [state, setState] = useState({
     isAuthenticated: false,
   });

  function handleChangeLabel(key, value) {
    setLabels({
      ...labels,
      [key]: value,
    });
  }

     if (state.isAuthenticated) {
      const handleSubmitLabel = (event) => {
        event.preventDefault();

        var myHeaders = new Headers();
        myHeaders.append(
          "Authorization",
          `Bearer ${localStorage.getItem("access_token")}`
        );
        myHeaders.append("Content-Type", "application/x-www-form-urlencoded");

        var urlencoded = new URLSearchParams();
        urlencoded.append("name", labels.label);

        var requestOptions = {
          method: "POST",
          headers: myHeaders,
          body: urlencoded,
          redirect: "follow",
        };

        fetch("https://codeminos-todo.tk/api/v1/labels", requestOptions)
          .then((response) => response.text())
          .then((json) => {
            const result = JSON.parse(json);
            setLabels(result.data);
             setState({
               isAuthenticated: true,
             });
          })
          .catch((error) => {
            setState({
               isAuthenticated: false,
             });
          });
      };
     }
  

  return (
    <>
      <form onSubmit={(event) => {handleSubmitLabel(event)}}>
        <span>
          <label>Add a Label to your task</label>
          
          {props.add_task_data.map(task => {
           <select onChange={handleChangeLabel} name="task-label">
             <option>{task}</option>
           </select>
          })}
         
        </span>
      </form>
      </>
  );       
      

  
  
}

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-hooks


    【解决方案1】:

    问题在于,当您尝试访问 Label.js 时,您正在期待 add_task_data 属性:

    export default function Label(props){
      
      // ...
    
      return (
        // ...
              // will throw when "add_task_data" prop value is *undefined*
              {props.add_task_data.map(task => {
                 // ...
              })}
        // ...
      );
    }
    

    然后,在 App.js 中,当你实例化组件时:

                  <Label {...add_task_data.title}/>
    

    你没有通过 add_task_data 预期的道具。 在这种情况下,您正在解构 add_task_data.title 的传播,它是一个 string,这对于您当前的场景似乎没有意义。

    解决您的问题,我相信这是您打算做的,只是将 Label 实例化为:

                  <Label {...add_task_data}/>
    

    【讨论】:

      【解决方案2】:

      当您将数据传递给孩子时,在父母中,您正在传递 &lt;Label {...add_task_data.title}/&gt; 这意味着你只传递了标题,但在子类中你试图映射你没有的整个数据。 所以改为传递整个数据集,如 &lt;Label {add_task_data}/&gt;

      【讨论】:

        猜你喜欢
        • 2023-02-22
        • 2021-06-01
        • 2020-01-25
        • 2019-12-08
        • 2020-01-21
        • 1970-01-01
        • 2021-06-25
        • 2021-09-25
        • 2020-12-26
        相关资源
        最近更新 更多