ReactJS prop 函数变得未定义
ReactJS prop function becomes undefined
我会简短的。标题完美地解释了主要问题,但我无法弄清楚这个 'function' 在哪里变成或未定义。在阅读代码之前让我解释一下。\ App render Shows,Shows render multiple Show extracted from 'show' state。但是如果你切换到 FAVS 选项卡,Shows Show 将从 'favs' 状态中提取出来。
如果你想自己测试一下:https://github.com/Zackysh/bug-free-fortnight/tree/main
应用程序可让您查找节目并在崩溃前将它们添加到收藏夹。当您再次转到 FAVS 选项卡并按下 fav 按钮时,它会崩溃,它应该删除此 fav 并更新 Shows,但它会崩溃。
首先,说明我要设置新值:
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 之前执行它。
第2.cannot appear as a descendant of <p>
。它是由<Typography>{children}</Typography>
,在function TabPanel(props)
,在FullWidthTabs.js
中引起的。您的 children
包含 div
和其他更高的元素,但是 Typography
return 是 p
。段落不应该包含容器,而只是简单的文本。
3rd. 在下面的卡片中,在您进行搜索后,单击星标图标后,崩溃是因为此处 if (shows.length === 1) return <Show show={shows[0]} />
内的这一行Show.js
。只有当您只有一张卡时才会发生。这是因为您永远不会将值 addRemoveFav
传递给组件 Show
,当它只有 1(又名 if === 1
)时。这存在于 Netflix
和 Favorite
页面中,只要它恰好是一张卡片。要修复它很简单:像这样传递 属性 addRemoveFav
if (shows.length === 1) return <Show show={shows[0]} addRemoveFav={addRemoveFav} />;
它可以解决您的问题。
当你有 2 张以上的卡片时,这不是问题的原因是,当卡片超过 1 张时,你执行 showList
函数,return 是 <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
prop 的数据。您可以使用以下方法轻松修复它:
<Col>
<Shows
addRemoveFav={onDelete}
fav={fav}
shows={fav ? showFavs() : showShows()}
/>
</Col>
思路还是一样。但现在您不必重复两次代码。
2nd. 你不需要做fav === true ? "" : ""
。 JavaScript 在验证值方面非常棒。一个简单的 fav ? "" : ""
就可以做到。 JavaScript 将 return false
如果值,在这种情况下,fav
是 null
、undefined
、空字符串或 false
.可能更多,不记得了。
这也适用于简单的 if
语句。此外,你甚至可以这样做{fav && <div>render me</div>}
。如果在最后,必须是最后,验证是某种反应子,在这种情况下,div
,它将 return 反应子。支票可以像您希望的那样复杂{((fav && try) || (!fav && number > 5)) && <div>render me with condition</div>}
3rd. 拆分组件。注意到单个文件中有多个功能组件(主要是App
)。它有点违反单一职责原则,因为文件负责多个内容。此外,文件变大,组件难以复用。只需为每个新功能或 class、component.
创建一个新文件
第 4. 更短 return 秒。有时你会拥有你知道的功能,这些功能将是 return 某物的单行代码。例如:
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 语句,因为有些人更喜欢这样。很高兴知道你能做到这一点。
5.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
的扩展。使用许多不同的语言,包括反应。如果你想改变一些东西,它是完全可定制的。安装后,您需要转到设置以启用它OnSave
,因此每当您保存文件时,它都会重新格式化您的代码以使其更漂亮。
希望这些建议对您有所帮助。你可能知道一些,也可能不知道。了解这些基础知识总是好的。
我会简短的。标题完美地解释了主要问题,但我无法弄清楚这个 'function' 在哪里变成或未定义。在阅读代码之前让我解释一下。\ App render Shows,Shows render multiple Show extracted from 'show' state。但是如果你切换到 FAVS 选项卡,Shows Show 将从 'favs' 状态中提取出来。
如果你想自己测试一下:https://github.com/Zackysh/bug-free-fortnight/tree/main
应用程序可让您查找节目并在崩溃前将它们添加到收藏夹。当您再次转到 FAVS 选项卡并按下 fav 按钮时,它会崩溃,它应该删除此 fav 并更新 Shows,但它会崩溃。
首先,说明我要设置新值:
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 之前执行它。
第2.cannot appear as a descendant of <p>
。它是由<Typography>{children}</Typography>
,在function TabPanel(props)
,在FullWidthTabs.js
中引起的。您的 children
包含 div
和其他更高的元素,但是 Typography
return 是 p
。段落不应该包含容器,而只是简单的文本。
3rd. 在下面的卡片中,在您进行搜索后,单击星标图标后,崩溃是因为此处 if (shows.length === 1) return <Show show={shows[0]} />
内的这一行Show.js
。只有当您只有一张卡时才会发生。这是因为您永远不会将值 addRemoveFav
传递给组件 Show
,当它只有 1(又名 if === 1
)时。这存在于 Netflix
和 Favorite
页面中,只要它恰好是一张卡片。要修复它很简单:像这样传递 属性 addRemoveFav
if (shows.length === 1) return <Show show={shows[0]} addRemoveFav={addRemoveFav} />;
它可以解决您的问题。
当你有 2 张以上的卡片时,这不是问题的原因是,当卡片超过 1 张时,你执行 showList
函数,return 是 <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
prop 的数据。您可以使用以下方法轻松修复它:
<Col>
<Shows
addRemoveFav={onDelete}
fav={fav}
shows={fav ? showFavs() : showShows()}
/>
</Col>
思路还是一样。但现在您不必重复两次代码。
2nd. 你不需要做fav === true ? "" : ""
。 JavaScript 在验证值方面非常棒。一个简单的 fav ? "" : ""
就可以做到。 JavaScript 将 return false
如果值,在这种情况下,fav
是 null
、undefined
、空字符串或 false
.可能更多,不记得了。
这也适用于简单的 if
语句。此外,你甚至可以这样做{fav && <div>render me</div>}
。如果在最后,必须是最后,验证是某种反应子,在这种情况下,div
,它将 return 反应子。支票可以像您希望的那样复杂{((fav && try) || (!fav && number > 5)) && <div>render me with condition</div>}
3rd. 拆分组件。注意到单个文件中有多个功能组件(主要是App
)。它有点违反单一职责原则,因为文件负责多个内容。此外,文件变大,组件难以复用。只需为每个新功能或 class、component.
第 4. 更短 return 秒。有时你会拥有你知道的功能,这些功能将是 return 某物的单行代码。例如:
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 语句,因为有些人更喜欢这样。很高兴知道你能做到这一点。
5.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
的扩展。使用许多不同的语言,包括反应。如果你想改变一些东西,它是完全可定制的。安装后,您需要转到设置以启用它OnSave
,因此每当您保存文件时,它都会重新格式化您的代码以使其更漂亮。
希望这些建议对您有所帮助。你可能知道一些,也可能不知道。了解这些基础知识总是好的。