javascript - react : Entering boolean 'true' as prop end up as 'false' in the component

标签 javascript reactjs typescript

我对此感到非常困惑。我有一个选择框组件,其中有一个选定的 Prop 。如果为 true,我会在框中显示一个复选标记,如果为 false,则不会。现在我遇到的问题是,点击三次后它不再切换。

最奇怪的是,我确实向组件的“selected”属性传递了一个 true bool 值(请参阅日志),但是当我在该子组件中记录“selected”属性的日志时,它说它是 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>
  );
};

最佳答案

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.concat 向数组添加值并返回新的数组引用。

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,
  };

关于javascript - react : Entering boolean 'true' as prop end up as 'false' in the component,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69521301/

相关文章:

reactjs - React 在打字时取消输入字段的焦点

reactjs - ant design 3.0 版表单上的 Typescript 错误

typescript - Rust WebAssembly 自定义元素内存释放错误

javascript - 跨 Controller 共享和观察数据

javascript - 如何在 JavaScript 中去除数组元素中的非整数

javascript - JS 发送帖子后停止监听事件

javascript - JQuery:不定位元素

javascript - 导入别名 'theme'的循环定义

javascript - 返回对象后这个数组的作用是什么?

typescript - 使用 Typescript 和 Electron 还需要 Babel 吗?