每天推薦一個 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