我有一个demo
这是一个使用Typescript的简单React应用。
我正在尝试使用Reacts Context API
我创建了一个上下文ThemeContext
,该上下文具有简单的主题样式值,可用于其他组件。
然后,我使用此主题上下文来设置书籍列表Booklist.tsx
我想要一个按钮来更新主题
我要从ThemeToggle组件调用的上下文中有一个主题。
我的问题是此ThemeToggle中的onClick出现错误
(JSX attribute) React.DOMAttributes<HTMLButtonElement>.onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
Type 'boolean' is not assignable to type '(event: MouseEvent<HTMLButtonElement, MouseEvent>) => void'.(2322)
ThemeToggle.tsx(23, 29): The expected type comes from property 'onClick' which is declared here on type 'DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>'
我确定这是一个打字稿错误,但不确定如何解决。
是什么导致onClick出现此错误,我该如何解决
index.tsx
import React from 'react';
import BookList from './Booklist';
import ThemeContextProvider from './ThemeContext';
import { render } from "react-dom";
import ThemeToggle from './ThemeToggle';
import './style.css'
const App:React.FC = () => {
return (
<div className="App">
<ThemeContextProvider>
<BookList />
<ThemeToggle/>
</ThemeContextProvider>
</div>
);
}
export default App;
render(<App />, document.getElementById("root"));
ThemeContext.tsx
import React, {createContext} from 'react'
export interface Props {}
export interface State {
lightTheme: boolean
light:{syntax: string, ui: string, bg: string}
dark:{syntax: string, ui: string, bg: string}
toggleTheme:boolean
}
const defaultState:State = {
lightTheme: true,
light:{syntax:'', ui:'', bg:''},
dark:{syntax:'', ui:'', bg:''},
toggleTheme:false
}
export const ThemeContext = createContext(defaultState)
class ThemeContextProvider extends React.Component<Props, State> {
constructor(props: Props){
super(props)
this.state = {
lightTheme: true,
light: {syntax: '#333', ui: 'pink', bg: '#bbb'},
dark: {syntax: '#ddd', ui: '#333', bg: '#555'},
toggleTheme: false
}
}
toggleTheme = () => {
this.setState({ lightTheme: !this.state.lightTheme})
}
render() {
return (
<ThemeContext.Provider value={{...this.state, toggleTheme: this.state.toggleTheme}}>
{this.props.children}
</ThemeContext.Provider>
);
}
}
export default ThemeContextProvider;
Booklist.tsx
import React from 'react'
import { ThemeContext } from './ThemeContext';
export interface Props {}
export interface State {
lightTheme: boolean
light:Darkness
dark:Darkness
}
interface Darkness{
syntax: string
ui: string
bg: string
}
class BookList extends React.Component<Props, State> {
render() {
return(
<ThemeContext.Consumer>
{(state) => {
const { lightTheme, light, dark} = state
const theme = lightTheme ? light : dark
return(
<div style={{color: theme.syntax, background: theme.bg}}>
<ul>
<li style={{background:theme.ui}}>Book One</li>
<li style={{background:theme.ui}}>Book Two</li>
</ul>
</div>
)
}}</ThemeContext.Consumer>
)
}
}
export default BookList;
ThemeToggle
import * as React from 'react';
import { ThemeContext } from './ThemeContext';
export interface ThemeToggleProps {}
export interface ThemeToggleState {}
class ThemeToggle extends React.Component<ThemeToggleProps, ThemeToggleState> {
render() {
return (
<ThemeContext.Consumer>
{(state) => {
const {toggleTheme} = state
return(
<button onClick={toggleTheme}>Toggle Theme</button>
)
}}
</ThemeContext.Consumer>
);
}
}
export default ThemeToggle ;
答案 0 :(得分:2)
就像@PhilipFeldmann在评论中写道,onclick
属性需要一个函数,而不是布尔值。
您在ThemeContext.tsx:12中声明了接口State
,其中属性toggleTheme
被声明为布尔值。保持这种状态,为const defaultState
中的属性分配一个布尔值,这与为ThemeContextProvider.state
属性为布尔值的对象分配toggleTheme
相同。然后将其传递给ThemeToggle类,该类中的toggleTheme仍然是一个布尔值(ThemeToggle.tsx:13)。
您可以通过更改State
接口的声明来解决此问题,以使toggleTheme
代替一个函数:
// ThemeContext.tsx:5
export interface State {
lightTheme: boolean
light:{syntax: string, ui: string, bg: string}
dark:{syntax: string, ui: string, bg: string}
toggleTheme:() => void
}
// ThemeContext.tsx:12
const defaultState:State = {
lightTheme: true,
light:{syntax:'', ui:'', bg:''},
dark:{syntax:'', ui:'', bg:''},
toggleTheme: () => {}
}
// ThemeContext.tsx:26
this.state = {
lightTheme: true,
light: {syntax: '#333', ui: 'pink', bg: '#bbb'},
dark: {syntax: '#ddd', ui: '#333', bg: '#555'},
toggleTheme: this.toggleTheme
}
该按钮将起作用。