如何在React计算器应用中将按键组件的按钮值传递到显示组件
可以通过状态提升的方案实现按键值到屏幕组件的传递,平级子组件共享的数据统一放到公共父组件App中管理即可,具体实现如下:
1 父组件App改造
将计算相关的状态和点击处理逻辑放到App组件,再透传给对应的子组件:
import * as React from "react" import { useState } from "react" // 新增导入useState import { ChakraProvider, Box, Text, Flex, Center, Spacer, Container, VStack, FormControl, FormLabel, Switch, useColorMode, useColorModeValue, Input, Grid, GridItem } from "@chakra-ui/react" import "@fontsource/spartan/700.css" import customTheme from "./theme" import CalculatorButton from "./button-component"; import FunctionalButton from "./function-component"; // 定义计算器状态类型 interface CalculatorData { currentValue: string; // 当前输入值 prevValue: string; // 上一次输入值 operator: string | null; // 选中的运算符 } export default function App(){ // 初始化计算器状态 const [calcData, setCalcData] = useState<CalculatorData>({ currentValue: "0", prevValue: "", operator: null }) // 按钮点击处理函数,后续算术运算逻辑也在这里实现 const handleButtonPress = (value: number | string) => { // 这里可以根据value类型(数字/运算符/功能键)写对应的处理逻辑 // 示例:点击数字直接更新当前显示值 if(typeof value === "number") { setCalcData(prev => ({ ...prev, currentValue: prev.currentValue === "0" ? String(value) : prev.currentValue + value })) } // 运算符、重置、删除、等于逻辑自行补充即可 } return ( <ChakraProvider theme={customTheme}> <Box bg={"bisque"} color={"white"} h="100vh"> {/* Main App Container */} <Box pt="10"> <Center> <VStack> {/* Top bar */} <TopBar /> {/* Result Display 传入要显示的值 */} <DisplayResult displayValue={calcData.currentValue} /> {/* Keys pad 传入点击处理函数 */} <KeypadButtons onButtonPress={handleButtonPress} /> </VStack> </Center> </Box> </Box> </ChakraProvider> ); }
2 DisplayResult组件改造
移除内部状态,接收父组件传入的显示值:
interface DisplayResultProps { displayValue: string; } function DisplayResult({ displayValue }: DisplayResultProps) { return ( <Box size="lg" mb="2" sx={{ width: "100%" }}> <Input placeholder="0" textAlign="right" p="10" bg={darkSaturatedBlue.screenBackgroundColor} border="none" fontSize="23" value={displayValue} readOnly // 禁止手动输入,只能通过按钮修改 /> </Box> ); }
接收父组件传入的点击函数,透传给每个按钮:
interface KeypadButtonsProps { onButtonPress: (val: number | string) => void; } function KeypadButtons({ onButtonPress }: KeypadButtonsProps) { return <Container bg={darkSaturatedBlue.toggleKeybadBackgroundColor} borderRadius="3" p="3"> <Grid templateColumns="repeat(4,1fr)" templateRows="repeat(5,1fr)" gap="2"> <CalculatorButton onClick={() => onButtonPress(7)} digit={7} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor} /> <CalculatorButton onClick={() => onButtonPress(8)} digit={8} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <CalculatorButton onClick={() => onButtonPress(9)} digit={9} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <FunctionalButton onClick={() => onButtonPress("DEL")} digit={"DEL"} color="white" size="md" boxShadow="md" /> <CalculatorButton onClick={() => onButtonPress(4)} digit={4} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <CalculatorButton onClick={() => onButtonPress(5)} digit={5} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <CalculatorButton onClick={() => onButtonPress(6)} digit={6} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <FunctionalButton onClick={() => onButtonPress("+")} digit={"+"} color="white" size="md" boxShadow="md" /> <CalculatorButton onClick={() => onButtonPress(1)} digit={1} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <CalculatorButton onClick={() => onButtonPress(2)} digit={2} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <CalculatorButton onClick={() => onButtonPress(3)} digit={3} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <FunctionalButton onClick={() => onButtonPress("-")} digit={"-"} color="white" size="md" boxShadow="md" /> <FunctionalButton onClick={() => onButtonPress(".")} digit={"."} color="white" size="md" boxShadow="md" /> <CalculatorButton onClick={() => onButtonPress(0)} digit={0} color="white" size="md" bg={darkSaturatedBlue.buttonDigitColor}/> <FunctionalButton onClick={() => onButtonPress("/")} digit={"/"} color="white" size="md" boxShadow="md" /> <FunctionalButton onClick={() => onButtonPress("x")} digit={"x"} color="white" size="md" boxShadow="md"/> <GridItem colSpan={2}> <FunctionalButton onClick={() => onButtonPress("RESET")} digit={"RESET"} color="teal" size="md" style={buttonStyle} boxShadow="md" /> </GridItem> <GridItem colSpan={2}> <FunctionalButton onClick={() => onButtonPress("=")} digit={"="} color="red" size="md" style={buttonStyle} boxShadow="md" /> </GridItem> </Grid> </Container>; }
4 按钮组件改造
接收onClick参数绑定到原生按钮事件:
4.1 CalculatorButton.tsx
import * as React from 'react'; import {Button} from '@chakra-ui/react'; interface CalculatorButtonProps { digit:Number, color:string, bg?:string, size:string, onClick: () => void; } const CalculatorButton: React.FC<CalculatorButtonProps> = ({digit,color,bg,size,onClick}) => { return ( <Button onClick={onClick} colorScheme="White" size={size} m="1" bg={bg} variant="solid"> {digit} </Button> ); } export default CalculatorButton;
4.2 FunctionalButton.tsx
import * as React from 'react'; import {Button} from '@chakra-ui/react'; interface FunctionalButtonProps { digit:string, color:string, boxShadow:string, size:string, style?:object, onClick: () => void; } const FunctionalButton : React.FC<FunctionalButtonProps> = ({digit,color,boxShadow,size,style,onClick}) => { return ( <Button onClick={onClick} colorScheme={color} size={size} sx={style} m="1" boxShadow={boxShadow}> {digit} </Button> ) } export default FunctionalButton;
后续所有的运算逻辑、重置、删除、等于计算的逻辑都可以直接在App组件的handleButtonPress函数中实现即可。
内容的提问来源于stack exchange,提问作者Esam Olwan
相关产品推荐
相关产品推荐

