前端框架React - State 和 生命周期

1.Introduction of state

the fact that the Clock sets up a timer and updates the UI every second should be an implementation detail of the .
事实上组件的功能和更新UI的代码应该是组件自己的具体实现细节。

ReactDOM.render(
  <Clock />,document.getElementById('root')
);


为了实现上述的代码,我们需要为组件增加state。
State is similar to props,but it is private and fully controlled by the component.
State和props很相似,但是state是私有的,完全由组件控制。
Wementioned beforethat components defined as classes have some additional features. Local state is exactly that: a feature available only to classes.

state是一个只在class定义的组件里面才有的新特性。

2.将function转换成Class

  1. Create anES6 classwith the same name that extendsReact.Component.

  2. Add a single empty method to it calledrender().

  3. 每一个Class类型的组件都要有一个render()方法。

  4. Move the body of the function into therender()method.

  5. Replacepropswiththis.propsin therender()body.

  6. 在render()方法中,props要用this.props来代替

  7. Delete the remaining empty function declaration.



class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello,world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}



3.给Class添加local state

我们将用下面的三步来完成date从props到state的过程:
1.在render()方法中,用this.state.date来代替this.props.date


class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello,world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}


2.添加一个class的构造函数来初始化this.state,并且我们把props传进了基础的构造函数。
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello,249)">3.Remove thedateprop from the<Clock />element 
  

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello,world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,document.getElementById('root')
);


4.添加生命周期方法到Class中

We want to set up a timer whenever the is rendered to the DOM for the first time. This is called "mounting" in React.
我们希望给Class安装一个计时器,可以知道Class什么时候第一渲染到DOM里面。这在React叫做mounting
We also want toclear that timerwhenever the DOM produced by theClockis removed. This is called "unmounting" in React.
我们也希望当这个Class的node被remove的时候能清除这个计时器。这叫做unmounting。
这些方法叫做生命周期钩子。
componentDidMount() { } 这个钩子在组件输出被渲染到DOM之后run。这里set计时器很好。
componentWillUnmount() { }
 componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),1000
    );
  }
注意我们将timerID保存在this里面。
Whilethis.propsis set up by React itself andthis.statehas a special meaning,you are free to add additional fields to the class manually if you need to store something that is not used for the visual output.
尽管this.props由React自己设置,this.state有特殊的意义。我们可以添加其他的filed到class,只要我们需要存储的东西不会用在视觉输出里面。
上面的翻译简直不是人话。意思是
If you don't use something inrender(),it shouldn't be in the state.
如果我们需要保存的东西不会被用在render()方法中,也就是不会用在视觉输出中,那么这些东西就不应该被保存在state里面。

Finally,we will implement thetick()method that runs every second.

It will usethis.setState()to schedule updates to the component local state:

最后我们用this.setState()方法来更新组件本地的state。

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello,249)">调用流程: 
  
1.Whenis passed toReactDOM.render()component. Sinceneeds to display the current time,it initializesthis.statewith an object including the current time. We will later update this state.
2.React then calls theClockcomponent'srender()method. This is how React learns what should be displayed on the screen. React then updates the DOM to match the's render output.

When theoutput is inserted in the DOM,React calls thecomponentDidMount()lifecycle hook. Inside it,thecomponent asks the browser to set up a timer to calltick()once a second.
4.Every second the browser calls thetick()method. Inside it,theClockcomponent schedules a UI update by callingsetState()with an object containing the current time. Thanks to thesetState()call,React knows the state has changed, and callsmethod again to learn what should be on the screen. This time,this.state.datein therender()method will be different,and so the render output will include the updated time. React updates the DOM accordingly.

5.If thecomponent is ever removed from the DOM,React calls thecomponentWillUnmount()lifecycle hook so the timer is stopped.


5.正确的使用State

1.不要直接改变state
// Wrong
this.state.comment = 'Hello';

我们要改变state,用setState这个方法

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

The only place where you can assign this.state is the constructor.
你唯一可以给this.state分配值的地方是构造函数。


2.state的更新可能是异步的
react可能在一次更新中批处理多个setState方法。

Because this.props and may be updated asynchronously,you should not rely on their values for calculating the next state.
因为更新可能是异步的,所以不要依赖他们的值来计算下一个state

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

To fix it,use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument,and the props at the time the update is applied as the second argument:

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


3.state的更新会被合并
When you callsetState()react会合并你向state里面提供的对象。
Then you can update them independently with separatecalls:
  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

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

The merging is shallow,sothis.setState({comments})leavesthis.state.postsintact,but completely replacesthis.state.comments.
合并会不管this.state.posts,只会更新this.state.comments


6.The data flow 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.
parent和child控件都不会知道一个控件是stateful还是stateless。

This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.
除了这个控件本身,其他控件是不能access 这个控件的state的。
A component may choose to pass its state down as props to its child components
一个控件可以选择将它的state作为props传递给它的子控件。
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>


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 's state,from the 's props,or was typed by hand:
这个组件会在它的props里面获得date,不会知道这个date来自Clock组件的state,来自Clock组件的props还是手动输入的。
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.
任何state都是被具体的state所拥有的。任何来自于那个state的数据或者UI只能影响低于这个state自己控件的控件。
一个完整的例子:
function FormattedDate(props) {
  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),world!</h1>
        <FormattedDate date={this.state.date} />
      </div>
    );
  }
}

function App() {
  return (
    <div>
      <Clock />
      <Clock />
      <Clock />
    </div>
  );
}

ReactDOM.render(<App />,document.getElementById('root'));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom