ReactJS使用有状态和无状态组件的正确方法?

ReactJS使用有状态和无状态组件的正确方法?,reactjs,components,containers,stateless,stateful,Reactjs,Components,Containers,Stateless,Stateful,我已经开始学习ReactJS,并对无状态和有状态组件提出了一个问题。一般来说,我遵循如下所示的组件和容器分离。有状态函数位于组件文件夹中,其他逻辑操作位于容器文件夹下。 让我们想想材质UI下拉列表 import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import InputLabel from '@material-ui/core/InputLabel'; import MenuIt

我已经开始学习ReactJS,并对无状态和有状态组件提出了一个问题。一般来说,我遵循如下所示的组件和容器分离。有状态函数位于组件文件夹中,其他逻辑操作位于容器文件夹下。

让我们想想材质UI下拉列表

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';

const useStyles = makeStyles(theme => ({
  button: {
    display: 'block',
    marginTop: theme.spacing(2),
  },
  formControl: {
    margin: theme.spacing(1),
    minWidth: 120,
  },
}));

export default function ControlledOpenSelect() {
  const classes = useStyles();
  const [age, setAge] = React.useState('');
  const [open, setOpen] = React.useState(false);

  const handleChange = event => {
    setAge(event.target.value);
  };

  const handleClose = () => {
    setOpen(false);
  };

  const handleOpen = () => {
    setOpen(true);
  };

  return (
    <div>    
      <FormControl className={classes.formControl}>
        <InputLabel id="demo-controlled-open-select-label">Age</InputLabel>
        <Select
          labelId="demo-controlled-open-select-label"
          id="demo-controlled-open-select"
          open={open}
          onClose={handleClose}
          onOpen={handleOpen}
          value={age}
          onChange={handleChange}
        >
          <MenuItem value="">
            <em>None</em>
          </MenuItem>
          <MenuItem value={10}>Ten</MenuItem>
          <MenuItem value={20}>Twenty</MenuItem>
          <MenuItem value={30}>Thirty</MenuItem>
        </Select>
      </FormControl>
    </div>
  );
}
从“React”导入React;
从'@material ui/core/styles'导入{makeStyles};
从“@material ui/core/InputLabel”导入InputLabel;
从“@material ui/core/MenuItem”导入菜单项;
从“@material ui/core/FormControl”导入FormControl;
从“@material ui/core/Select”导入Select;
const useStyles=makeStyles(主题=>({
按钮:{
显示:“块”,
marginTop:主题。间距(2),
},
表单控制:{
边距:主题。间距(1),
最小宽度:120,
},
}));
导出默认函数ControlleOpenSelect(){
const classes=useStyles();
常量[年龄,设置]=React.useState(“”);
const[open,setOpen]=React.useState(false);
const handleChange=事件=>{
设置(事件、目标、值);
};
常量handleClose=()=>{
setOpen(假);
};
const handleOpen=()=>{
setOpen(真);
};
返回(
年龄
没有一个
十
二十
三十
);
}
为了打开和关闭下拉列表,方法更改打开状态,这意味着它是有状态组件。但没有其他变化(忽略年龄设置)。它似乎是可重用的组件,但包含状态,具有非常简单的打开和关闭操作。我应该放在哪个文件夹里?容器还是组件

实际上,除了文件夹选择之外,我还可以将打开状态作为回调函数,将打开状态作为道具。但我认为在每个容器中执行此操作可能会有点过火,因为只需打开下拉列表(React.memo可以处理它,但在任何地方使用它似乎都很奇怪),所以会重新渲染父容器

1-使用简单操作的正确方法是什么?将功能作为道具或组件中的使用状态

2-如果我使用道具,由于整个其他组件渲染,渲染是否会导致性能问题

提前感谢。

容器组件: 这些组件执行重逻辑,并且主要基于路由或(更确切地说是重逻辑)基于逻辑

功能组件: 这些函数很小(或可能很大),但主要用途是它们在几个容器组件中可用,事件可能在其他函数组件中可用,函数组件的用途是信誉,如果它们保持某种状态(比如在您的情况下保持一个简单的钩子状态以跟踪切换)我可以说这完全没关系

大多数情况下,您会发现自己在路由级别使用容器组件,并且连接了Redux(我还应该注意,现在不鼓励这样做)和嵌套在子组件中的许多其他功能组件

为了回答你们的问题,我可以说:

  • 对于简单操作,无需在父级中保持状态
    组件并将其传递给您的功能组件, 这会导致您将大量道具传递给您的子组件 使项目维护变得如此棘手,并导致错误代码, 在子组件中保存简单状态是完全可以的
  • 我想没有那么多,如果你只通过简单的道具

  • 与使用基于类的组件或询问有状态或无状态组件相比,在功能组件中使用新功能,react hook&context更好谢谢!,我也这么想,小手术也是可以做的。正如您所说的,在路由级别使用容器组件在路由发生时通常使用容器。也许可以使用子容器来降低复杂性。为什么你还说我应该注意,这几天我很沮丧?根据丹·阿布罗莫夫的文章,我读了一些我不记得的地方:))这与我的问题无关。正如你所看到的,我用了钩子。也许可以使用上下文,但不需要进行切换。