应该在哪里定义状态?

Posted

技术标签:

【中文标题】应该在哪里定义状态?【英文标题】:Where should a state be defined? 【发布时间】:2019-06-07 05:38:00 【问题描述】:

这两种在 React 中定义状态的结构有什么区别?

class ProductsPage extends Component 
  constructor(props) 
    super(props);
    this.state = 
      products: []
    ;
  
  ...

还有这个:

class ProductsPage extends Component 
  state = 
    products: []
  ;
  ...

在 ES6 中编码时,它们都可以很好地工作。但是,较低的似乎在 typescript 3 中不起作用。我有以下内容:

interface IState 
  products: IProduct[];


class ProductsPage extends Component<, IState> 
  state = 
    products: []
  ;


  public componentDidMount() 
    this.setState( products );
  

  public render() 
    return (
      <div className="page-container">
        <ul className="product-list">
          this.state.products.map(p => (
            <li className="product-list-item" key=p.id>
              p.name
            </li>
          ))
        </ul>
      </div>
    );
  

并且 ts 编译器标记了一个错误:“never”类型上不存在属性 ID

这是为什么呢?

【问题讨论】:

【参考方案1】:

第二种形式是class properties,它是第 3 阶段的 javascript 提案(意味着它还不是该语言的一部分)。在构造函数上添加属性是old ES2015 way(称为最大最小类)。

在您的情况下,没有功能差异。

TypeScript 要求您为类型安全声明类字段 - 因此会发出警告。

【讨论】:

【参考方案2】:

如何定义 React 组件的状态与 React 推广的编码风格一样主观。通常我会走非常严格的路线,如下所示:

type State = 
    someStateVar: number[];
;

export class MyComponent extends Component<, State> 
    public readonly state: State = 
        someStateVar: [],
    ;

    public async componentDidMount() 
        // Dynamically fetch data (maybe via axios) and populate the new state
        const data = await axios.get<number[]>(...);
        this.setState( someStateVar: data );
    

如您所见,我明确地将 state 标记为只读,只是确保没有人尝试直接写入它(即使现在 IDE 和 linter 可以在没有预防措施的情况下检查这些错误)。

我不喜欢手动设置状态的另一个原因是它可能会鼓励错误的状态处理。永远不要在不使用setState 的情况下在类方法中直接将某些东西分配给state

此外,我基本上是立即定义默认值并使用componentDidMount 中的动态数据填充状态。这种方法允许您通过删除显式构造函数定义来保持代码简洁,因为无论如何您都应该将这样的初始化移动到componentDidMount,并且如果您不使用类成员箭头表示法,则仅将构造函数用于绑定方法第一名。

【讨论】:

谢谢克里斯蒂安!

以上是关于应该在哪里定义状态?的主要内容,如果未能解决你的问题,请参考以下文章

在 React Flux 上,我应该在哪里填充我的 Store 的初始状态?

在 React 中分离有状态和无状态组件的线应该在哪里?

Flux:中间错误应该存储在哪里?

CCL IVideoCastConsumer onFailed 状态代码在哪里定义?

使用 Relay 的嵌套表单组件 UI 中的状态应该在哪里?

在 Redux 中更改 props 但不更改状态的 API 调用应该放在哪里?