![](/img/trans.png)
[英]“Cannot read property 'map' of undefined” when trying to map out state and pass it as props into component
[英]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.