如何解决ReactJS prop 函数变得未定义
我会很简短。标题完美地解释了主要问题,但我无法弄清楚这个“函数”在哪里变成或未定义。在阅读代码之前让我解释一下。\ App render Shows,Shows 渲染从'show'状态提取的多个Show。但是,如果您更改为 FAVS 选项卡,Shows Show 将从“favs”状态中提取。
如果你想自己测试:https://github.com/Zackysh/bug-free-fortnight/tree/main
应用程序可让您在崩溃前查找节目并将其添加到收藏夹。当您再次转到 FAVS 选项卡并按收藏按钮时它会崩溃,它应该删除此收藏并更新节目,但它崩溃了。
首先,说明我想设置新值:
const [shows,setShows] = useState([]) // this one receives a bunch of shows with unique id
const [favs,setFavs] = useState([]) // this one will contain user fav shows
const [fav,setFav] = useState(false)
崩溃开始的 App.js 行:
return (
<div className="application">
// here 'fav' state change depends on which tab u visit (all shows / fav shows)
<FullWidthTabs setFav={setFav} filter={filter} setFilter={setFilter} />
<div id="mainBody" className="container text-center">
<ul id="results">
</ul>
</div>
<footer className="text-center">
<Container>
<Row>
<Col>
{ // look here -------------------
fav === true
? <Shows addRemoveFav={addRemoveFav} fav={fav} shows={showFavs()} />
: <Shows addRemoveFav={addRemoveFav} fav={fav} shows={showShows()} />
} // look here -------------------
</Col>
</Row>
</Container>
</footer>
</div>
)
好的,这里是 addRemoveFav 函数:
const addRemoveFav = (show) => {
if (favs.length != 0) {
const result = favs.filter(fav => show.show_id == fav.show_id)
if (result.length < 1) {
setFavs(favs.concat(show))
} else {
setFavs(favs.filter(fav => fav.show_id !== show.show_id))
}
} else {
setFavs(favs.concat(show))
}
}
在此处显示:
const Shows = ({ shows,addRemoveFav }) => {
console.log('ADD REMOVE FAV JODER');
console.log(addRemoveFav);
const showList = () => shows.map(show =>
<Show addRemoveFav={addRemoveFav} key={show.show_id} show={show} />
)
if (shows.length === 1) return <Show show={shows[0]} />
if (shows.length < 10 && shows.length > 0) return <>{showList()}</>
if (shows.length > 20) return <p>Too many matches,specify another filter</p>
return <p>No matches</p>
}
显示组件,它更大所以只是相关的行;
const Show = ({ show,addRemoveFav }) => {
// ( .... )
return (
// ( .... )
<button
type="button"
className="btn btn-outline-success btn-floating"
data-mdb-ripple-color="dark"
onClick={() => addRemoveFav(show)} // here it sends current show object
/>
解决方法
有3个主要错误
1st. 错误 Cannot read property 'Component' of undefined
不是由任何变量、组件甚至反应代码引起的。它在您的 index.html
内。删除脚本行 <script src="https://npmcdn.com/react-log-state"></script>
修复了错误。将它移到 react 组件中,因为它需要 react 本身提供一些东西,并且在 react 之前执行它。
第二个。cannot appear as a descendant of <p>
。它由 <Typography>{children}</Typography>
引起,在 function TabPanel(props)
中的 FullWidthTabs.js
。您的 children
包含 div
和其他高级元素,但 Typography
返回 p
。段落不应包含容器,而应包含简单的文本。
3rd. 在下面的卡片中,在您进行搜索后,在您单击星形图标后,发生崩溃的原因是您的 if (shows.length === 1) return <Show show={shows[0]} />
中的此行 Show.js
.只有当您只有 1 张卡时才会发生这种情况。这是因为当它只有 1(又名 addRemoveFav
)时,您永远不会将值 Show
传递给组件 if === 1
。只要它恰好是一张卡片,它就存在于 Netflix
和 Favorite
页面中。修复它很简单:像这样传递 addRemoveFav
属性 if (shows.length === 1) return <Show show={shows[0]} addRemoveFav={addRemoveFav} />;
并解决您的问题。
当您有 2 张以上的卡片时,这不是问题的原因是因为有 1 张以上的卡片,您执行 showList
函数,该函数返回 <Show addRemoveFav={addRemoveFav} key={show.show_id} show={show} />
的映射数组和 Show
具有 addRemoveFav
属性的组件。
建议
一些改进代码的建议
1st. 渲染。你有这个
<Col>
{
fav === true
? <Shows addRemoveFav={onDelete} fav={fav} shows={showFavs()} />
: <Shows addRemoveFav={onDelete} fav={fav} shows={showShows()} />
}
</Col>
它打破了 DRY(不要重复自己)原则,因为代码本身会重复多次,只需要更改 - 提供给 shows
道具的数据。您可以通过以下方式轻松修复它:
<Col>
<Shows
addRemoveFav={onDelete}
fav={fav}
shows={fav ? showFavs() : showShows()}
/>
</Col>
想法还是一样的。但现在您不必重复两次代码。
第二个。您不需要执行 fav === true ? "" : ""
。 JavaScript 在验证值方面非常出色。一个简单的 fav ? "" : ""
就可以做到。如果值(在本例中为 false
)是 fav
、null
、空字符串或 undefined
,JavaScript 将返回 false
。可能更多,不记得了。
这也适用于简单的 if
语句。此外,您甚至可以这样做{fav && <div>render me</div>}
。如果最后必须是验证的结尾,则验证是某种反应子项,在这种情况下,div
,它将返回该反应子项。支票可以随心所欲{((fav && try) || (!fav && number > 5)) && <div>render me with condition</div>}
第三。 拆分您的组件。注意到单个文件中有多个功能组件(主要是App
)。它有点违反单一职责原则,因为文件负责多个内容。此外,文件变大,组件难以重复使用。只需为每个新的功能组件或类组件创建一个新文件。
第四。 回报更短。有时您会拥有一些函数,您知道这些函数将是一行代码来返回某些内容。例如这个:
const showFavs = () => {
return favs.filter((show) =>
JSON.stringify(show).toLowerCase().includes(filter.toLowerCase())
);
};
你可以简单地做:
const showFavs = () =>
favs.filter((show) =>
JSON.stringify(show).toLowerCase().includes(filter.toLowerCase())
);
这不是必需的。很多时候你会看到这样的函数带有 return 语句,因为有些人喜欢这样。很高兴知道您可以做到这一点。
第五。 Console.log()
。为了安慰你不必只传入字符串或变量。实际上,您可以将字符串和数组、函数或其他任何内容组合到一行中。所以,而不是:
console.log("ADD REMOVE FAV JODER");
console.log(addRemoveFav);
做console.log("ADD REMOVE FAV JODER",addRemoveFav);
。测试时,您的控制台将减少垃圾邮件。也更容易导航。
6th. OnClick 就地执行功能。而不是创建一个新函数 const tryToFix = () => addRemoveFav(show);
只是为了将它传递给 onClick={tryToFix}
有点没用。你在里面没有做任何逻辑。这样你就可以在没有任何新函数onClick={() => addRemoveFav(show)}
的情况下当场执行它。注意,如果您执行函数(如 function()
)而不只是传递引用(如 function
),则必须使用箭头或简单的函数 () =>
,因为它会在加载时执行,而不是在点击时执行。
7th. 让代码更漂亮!加载您的文件后,我的 IDE 对其进行了有趣的改造。如果您使用 VSC(react 会推荐它),请安装一个名为 Prettier
的扩展。适用于许多不同的语言,包括 react。如果你想改变一些东西,它是完全可定制的。安装后,您需要转到设置以启用它OnSave
,因此每当您保存文件时,它都会重新格式化您的代码以使其更美观。
希望这些建议有所帮助。你可能知道一些,也可能不知道。了解这些基础知识总是好的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。