我正在练习useContext
挂钩与Next.js
,如果它的问题,并创建了一个小网站,改变背景颜色的<Paragraph></Paragraph>
元素打印文本和<Button></Button>
元素改变主题。我组织它与<Layout />
的按钮和段落的地方。
正如在教程中所写的,我可以将这个主题更改逻辑放入onClick
方法中,它将工作。它实际上工作,但前提是我放入一个简单的<button></button>
元素,而不是react组件:
<ThemeContext.Provider value={theme}>
<Paragraph>Hello Context</Paragraph>
// Doesn't work ---> <Button type="button" onClick={() => {theme === 'dark' ? setTheme('light') : setTheme('dark')}}>Change theme</Button>
// Works ---> <button type="button" onClick={() => {theme === 'dark' ? setTheme('light') : setTheme('dark')}}>Change theme</button>
</ThemeContext.Provider>
Paragraph.tsx:
import { useContext, useState, ReactNode, DetailedHTMLProps, HTMLAttributes } from 'react';
import styles from './Paragraph.module.scss'
import cn from 'classnames'
import { ThemeContext } from '../../Layout/Layout'
interface ParagraphProps extends DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement> {
children: ReactNode
}
export const Paragraph = ({ children, className }: ParagraphProps): JSX.Element => {
const theme = useContext<string>(ThemeContext)
return (
<p className={cn(styles.p, className, {
[styles.paraDark]: theme === 'dark',
[styles.paraLight]: theme === 'light'
})}>
{children}
</p>
)
}
Button.tsx:
import { DetailedHTMLProps, ButtonHTMLAttributes, ReactNode, useContext, useState, MouseEventHandler } from 'react';
import { ThemeContext } from 'Layout/Layout';
import cn from 'classnames'
import styles from './Button.module.scss'
interface ButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
children: ReactNode
}
export const Button = ({ children, className}: ButtonProps ): JSX.Element => {
const theme = useContext<string>(ThemeContext)
return (
<button
className={cn(styles.button, className, {
[styles.buttonDark]: theme === 'dark',
[styles.buttonLight]: theme === 'light'
})}
>
{children}
</button>
)
}
Layout.tsx:
import { Paragraph, Button } from "Components";
import { createContext, useState } from 'react';
interface Layout {}
export const ThemeContext = createContext<string>('')
export const Layout = (): JSX.Element => {
const [theme, setTheme] = useState<string>('dark')
// Putting this function into onClick event also doesn't help
const handleChangeThemeButtonClick = () => {
if (theme === 'dark')
setTheme('light')
else if (theme === 'light')
setTheme('dark')
}
return (
<ThemeContext.Provider value={theme}>
<Paragraph>Hello Context</Paragraph>
<Button type="button" onClick={() => {theme === 'dark' ? setTheme('light') : setTheme('dark')}}>Change theme</Button>
<button type="button" onClick={() => {theme === 'dark' ? setTheme('light') : setTheme('dark')}}>Change theme</button>
</ThemeContext.Provider>
)
}
我是在react beta docs上学习这个钩子的,我的代码看起来和本教程中写的一样。
2条答案
按热度按时间7kqas0il1#
您的Button组件没有
onClick
属性。您需要将其作为prop传递下来,并从原生按钮
onClick
属性调用它。由于您使用的是typescript,因此请为其给予适当的类型
MouseEventHandler<HTMLButtonElement>
,并将其标记为可选(在类型声明中的属性名称后加上?
),以防您希望在不使用onClick事件的情况下使用Button。p8h8hvxi2#
您似乎尚未向Button组件添加onClick处理程序。您可以向Button组件内的button元素添加onClick事件侦听器,如下所示:
不要忘记处理onClick的 prop ,我建议称之为其他东西,如“onPress”,不要与本机onClick事件混淆。