代码之家  ›  专栏  ›  技术社区  ›  tilly

反应:在组件中输入布尔值“true”作为prop,结果为“false”

  •  0
  • tilly  · 技术社区  · 4 年前

    我完全被这搞糊涂了。我有一个选择框组件,其中我有一个选择的道具。如果为true,则在框中显示复选标记,如果为false,则不显示。现在我遇到的问题是,点击三次后,它不再切换。

    有人知道为什么会有不同吗?

    日志结果如下所示

    enter image description here

    父组件:Services.tsx

        import React, { useReducer } from "react";
    import { makeStyles } from "@material-ui/core";
    import { ToggleBox } from "components/ToggleBox";
    
    const useStyles = makeStyles((theme) => ({
      container: {
        display: "flex",
      },
    }));
    
    const servicesReducer = (state, action) => {
      switch (action.type) {
        case "toggle option":
          const isCurrentlySelected = state.selectedOptions.includes(
            action.payload.name
          );
          let newSelectedOptions = state.selectedOptions;
    
          if (isCurrentlySelected) {
            newSelectedOptions = newSelectedOptions.filter(
              (item) => item !== action.payload.name
            );
          } else {
            newSelectedOptions.push(action.payload.name);
          }
    
          return {
            ...state,
            selectedOptions: newSelectedOptions,
          };
        case "add options":
          return {
            ...state,
          };
      }
    };
    
    export const Services = () => {
      const classes = useStyles();
      const [state, dispatch] = useReducer(servicesReducer, {
        financialPlanning: {
          description: "",
          minHours: null,
          maxHours: null,
          minPrice: null,
          maxPrice: null,
        },
        selectedOptions: [],
      });
    
      const check = state.selectedOptions.includes("financialPlanning");
      console.log("check", check);
      console.log("check2", state);
    
      return (
        <div className={classes.container}>
            <ToggleBox
              selected={check}
              onClick={() => {
                console.log("click");
                dispatch({
                  type: "toggle option",
                  payload: { name: 'financialPlanning' },
                });
              }}
              title="Financiële planning"
            >
              Hey
            </ToggleBox>
        </div>
      );
    };
    

    子组件:ToggleBox.tsx

    import React from 'react';
    
    import { Box, Card, CardContent, Typography } from '@material-ui/core';
    import { makeStyles } from '@material-ui/core/styles';
    import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
    import CheckCircleOutlineIcon from '@material-ui/icons/CheckCircleOutline';
    import { responsivePadding } from 'helpers';
    
    export interface ToggleBoxProps {
      title: string;
      description?: string;
      rightIcon?: React.ReactElement;
      selected: boolean;
      focused?: boolean;
      children?: React.ReactNode;
      onClick?: () => void;
    }
    
    const useStyles = makeStyles(theme => ({
      root: ({ selected, focused }: ToggleBoxProps) => {
        let borderColor = theme.palette.grey[300];
        if (focused) {
          borderColor = theme.palette.primary.main;
        } else if (selected) {
          // eslint-disable-next-line prefer-destructuring
          borderColor = theme.palette.grey[500];
        }
    
        return {
          border: `1px solid ${borderColor}`,
          height: '100%',
        };
      },
      content: {
        height: '90%',
        display: 'flex',
        flexDirection: 'column',
      },
      header: {
        display: 'flex',
        cursor: 'pointer',
        flexDirection: 'row',
        justifyContent: 'space-between',
        paddingBottom: theme.spacing(2),
        marginBottom: theme.spacing(2),
        borderBottom: `1px solid ${theme.palette.divider}`,
        color: theme.palette.text.secondary,
      },
      title: {
        flex: 1,
        marginLeft: theme.spacing(2),
      },
    }));
    
    export const ToggleBox: React.FC<ToggleBoxProps> = (
      props: ToggleBoxProps,
    ) => {
      console.log('props toggleBox', props);
      const { title, description, rightIcon, selected, children, onClick } = props;
      console.log('selected check prop Togglebox', selected);
    
      const classes = useStyles(props);
    
      return (
        <Card className={classes.root}>
          <CardContent className={classes.content}>
            <Box className={classes.header} onClick={onClick}>
              {selected ? <CheckCircleOutlineIcon /> : <RadioButtonUncheckedIcon />}
              <Typography className={classes.title} color='textSecondary'>
                {title}
              </Typography>
              {rightIcon}
            </Box>
            <Typography variant='body2' color='textSecondary'>
              {description}
            </Typography>
            {selected && children}
          </CardContent>
        </Card>
      );
    };
    
    1 回复  |  直到 4 年前
        1
  •  1
  •   Drew Reese    4 年前

    当你给系统添加一个值时,你似乎在改变你的状态 selectedOptions .push

    case "toggle option":
      const isCurrentlySelected = state.selectedOptions.includes(
        action.payload.name
      );
      let newSelectedOptions = state.selectedOptions; // <-- saved reference to state
    
      if (isCurrentlySelected) {
        newSelectedOptions = newSelectedOptions.filter(
          (item) => item !== action.payload.name
        );
      } else {
        newSelectedOptions.push(action.payload.name); // <-- mutation!
      }
    
      return {
        ...state,
        selectedOptions: newSelectedOptions,
      };
    

    无论是添加还是删除,都必须返回一个新的数组引用。你可以用 Array.prototype.concar 向数组添加值并返回新的数组引用。

    case "toggle option":
      const isCurrentlySelected = state.selectedOptions.includes(
        action.payload.name
      );
    
      let newSelectedOptions = state.selectedOptions;
    
      if (isCurrentlySelected) {
        newSelectedOptions = newSelectedOptions.filter(
          (item) => item !== action.payload.name
        );
      } else {
        newSelectedOptions.concat(action.payload.name); // <-- add to and return new array
      }
    
      return {
        ...state,
        selectedOptions: newSelectedOptions,
      };