每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg


今日推荐开源项目:《前端互动问答环节 Front-End-FAQ》传送门:GitHub链接

推荐理由:在前端学习过程中遇上了不懂的问题?这个项目就是一个可以交流前端问题的平台,你可以在这里浏览别人提出的问题,也可以很简单的去提问或者回答补充里面的一些问题,在学习遇到困难时不妨来这里看看有没有人已经对你的问题作出了解答。


今日推荐英文原文:《What is State in React?》作者:Dina Hafez

原文链接:https://medium.com/@deedee8/what-is-state-in-react-7e4ba938df23

推荐理由:介绍 React 中的与 State 有关的知识,推荐正在学习 React 的同学一读

What is State in React?

State is a JavaScript object that stores component’s dynamic data and it enables a component to keep track of changes between renders. Because state is dynamic, it is reserved only for interactivity so you don’t use it for static React projects.

Components defined as classes have some additional features. Local state is exactly that: a feature available only to classes. State can only be used within a class and usually the only place where you can assign this.state is the constructor.

class Greeting extends React.Component { constructor() { super(); this.state = { name: 'John Smith' } } render() { return <h1>Hello, my name is { this.state.name }</h1>; } }

Nowadays you can use state without the constructor by using Property initializers which is a new feature came out in 2017.

class Greeting extends React.Component { state = { name: 'John Smith' } } render() { return <h1>Hello, my name is { this.state.name }</h1>; } }

State is managed within the component (similar to variables declared within a function). State in React Component is its own local state, which means the state cannot be accessed and modified outside the component and can only be used inside it, probably that will remind you of a function own local scope.

What does setStatedo?

setState() schedules an update to a component’s state object. When state changes, the component responds by re-rendering.

Using State Correctly

  • Do Not Modify State Directly
  • State Updates May Be Asynchronous
  • State Updates are Merged

Do Not Modify State Directly

Let’s start explaining one at a time. The first point requires not to modify state directly as it will not re-render a component like the following example:

// Wrong
this.state.comment = 'Hello';

Instead you should use setState() like this:

// Correct
this.setState({comment: 'Hello'});

And as I mentioned before the only place where you can assign this.state is the constructor.

State Updates May Be Asynchronous

React may batch multiple setState() calls into a single update for performance.

Calls to setState are asynchronous when they are inside event handlers and that when you don’t rely on this.state to reflect the new value immediately after calling setState.

incrementCount() {
  // Note: this will *not* work as intended.
  this.setState({count: this.state.count + 1});
}

handleSomething() {
  // Let's say `this.state.count` starts at 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();
  // When React re-renders the component, `this.state.count` will be 1, but you expected 3.

  // This is because `incrementCount()` function above reads from `this.state.count`,
  // but React doesn't update `this.state.count` until the component is re-rendered.
  // So `incrementCount()` ends up reading `this.state.count` as 0 every time, and sets it to 1.

To fix it, use a second form of setState that accepts a function rather than an object to ensure the call always uses the most updated version of state.

Passing an update function allows you to access the current state value inside the updater. Since setState calls are batched, this lets you chain updates and ensure they build on top of each other instead of conflicting:

incrementCount() {
  this.setState((state) => {
    // Important: read `state` instead of `this.state` when updating.
    return {count: state.count + 1}
  });
}

handleSomething() {
  // Let's say `this.state.count` starts at 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();

  // If you read `this.state.count` now, it would still be 0.
  // But when React re-renders the component, it will be 3.
}

Also you can pass props as a second argument at the time the update is applied:

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

State Updates are Merged

When you call setState(), React merges the object you provide into the current state.

For instance, your state may contain several independent variables:

constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

Then you can update them independently with separate setState() calls:

componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

The merging is shallow, so this.setState({comments}) leaves this.state.posts intact, but completely replaces this.state.comments.

You might be asking what is ComponentDidMount() and how it is used. It is a method that is invoked immediately after a component is mounted (inserted into the tree). Initialization that requires DOM nodes should go here. So if you need to load data from a remote endpoint (API), this is a good place to instantiate the network request.

As you can see in the above example the properties for this.state are now independent and separately added this.setState , passed an object to each property and surrounded them by ComponentDidMount() where they will be added to the DOM tree after we get the response from the fetchPosts() and fetchComments().

To read more about setState() check this link.


The Data Flows Down

Neither parent nor child components can know if a certain component is stateful or stateless, and they shouldn’t care whether it is defined as a function or a class.

It is not accessible to any component other than the one that owns and sets it. That is why state is often called local or encapsulated.

A component may choose to pass its state down as props to its child components.

This also works for user-defined components:

<FormattedDate date={this.state.date} />

The FormattedDate component would receive the date in its props and wouldn’t know whether it came from the Clock’s state, from the Clock’s props, or was typed by hand:

function FormattedDate(props) {
  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}

This is commonly called a top-down or unidirectional data flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components “below” them in the tree.

Components are truly isolated and are updated independently.

State is optional. Since state increases complexity and reduces predictability, a Component without state is preferable. Though you need to work with state for interactive apps, you should avoid using many Stateful Components.


每天推荐一个 GitHub 优质开源项目和一篇精选英文科技或编程文章原文,欢迎关注开源日报。交流QQ群:202790710;微博:https://weibo.com/openingsource;电报群 https://t.me/OpeningSourceOrg