反应打字稿-类型'布尔'不可分配给类型

时间:2020-09-21 13:02:22

标签: reactjs typescript

我有一个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 ;    

1 个答案:

答案 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
}

该按钮将起作用。