簡體   English   中英

TypeError: Cannot read property 'map' of undefined 當我嘗試 map 通過從父組件傳遞到子組件的道具時顯示

[英]TypeError: Cannot read property 'map' of undefined is showing when I'm trying to map over the props passed from parent component to child component

我在從父組件(App.js)到子組件(Label.js)的傳遞道具上映射問題。 終端向我顯示編譯成功並帶有警告。 當我在我的應用程序中單擊登錄按鈕時,我直接收到一條警報:“無法讀取未定義的屬性 'map'”,單擊確定后,顯示此錯誤:“TypeError: Cannot read property 'map' of undefined is顯示當我嘗試 map 處理從父組件傳遞到子組件的道具時”。 我是 React 鈎子的新手,非常感謝任何幫助,請原諒長行代碼。 謝謝

應用程序.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>
    </>
  );
}

Label.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>
      </>
  );       
      

  
  
}

在父級中,當您將數據傳遞給子級時,您正在傳遞<Label {...add_task_data.title}/>這意味着您僅傳遞標題,但在子級 class 中,您正在嘗試 map 您沒有的整個數據。 所以改為傳遞整個數據集,如<Label {add_task_data}/>

問題是您期望在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}/>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM