学习State
大约 3 分钟
class
查看示例代码
写法一
import React from "react";
export default class App extends React.Component {
  //定义数据
  constructor() {
    super();
    this.state = {
      total: 0,
    };
  }
  decrement() {
    if (this.state.total == 0) return;
    //更新数据
    this.setState({
      total: this.state.total - 1,
    });
  }
  increment() {
    if (this.state.total == 10) return;
    this.setState({
      total: this.state.total + 1,
    });
  }
  render() {
    const { total } = this.state;
    return (
      <>
        <h2>{total}</h2>
        <button onClick={this.decrement.bind(this)}>减少</button>
            
        <button onClick={this.increment.bind(this)}>增加</button>
      </>
    );
  }
}
写法二
import React from "react";
export default class App extends React.Component {
  //定义数据,相当于写法一少了constructor
  state = {
    total: 0,
  };
  decrement() {
    if (this.state.total == 0) return;
    this.setState({
      total: this.state.total - 1,
    });
  }
  increment() {
    if (this.state.total == 10) return;
    this.setState({
      total: this.state.total + 1,
    });
  }
  render() {
    const { total } = this.state;
    return (
      <>
        <h2>{total}</h2>
        <button onClick={this.decrement.bind(this)}>减少</button>
            
        <button onClick={this.increment.bind(this)}>增加</button>
      </>
    );
  }
}
hook
查看示例代码
写法一
import React, { useState } from "react";
const App = () => {
  const [count, setCount] = useState(0);
  const decrement = () => {
    if (count == 0) return;
    setCount(count - 1);
  };
  const increment = () => {
    if (count == 10) return;
    setCount(count + 1);
  };
  return (
    <>
      <h2>{count}</h2>
      <button onClick={decrement.bind(this)}>减少</button>
          
      <button onClick={increment.bind(this)}>增加</button>
    </>
  );
};
export default App;
写法二
import React, { useState } from "react";
const App = () => {
  const [count, setCount] = useState(0);
  return (
    <>
      <h2>{count}</h2>
      <button onClick={() => (count == 0 ? null : setCount(count - 1))}>减少</button>
          
      <button onClick={() => (count == 10 ? null : setCount(count + 1))}>增加</button>
    </>
  );
};
export default App;
setState更新是同步还是异步
setState更新数据会引起视图的重绘。
setState在可控的情况下是同步的,在非可控的情况下是同步的。
更新数据视图重绘的步骤:
更新state -> 创建新的window节点 -> 经过diff对比差异 -> 决定要渲染哪一部分 -> 真正的渲染 -> 形成新的UI
那我们该如何在修改数据后立即获得最新的数据呢?
查看示例代码
class组件通过回调函数
import React from "react";
export default class App extends React.Component {
  state = {
    total: 0,
  };
  increment() {
    this.setState(
      {
        total: this.state.total + 1,
      },
      () => {
        console.log("回调函数里获取:", this.state.total);
      }
    );
    console.log("直接获取:", this.state.total);
  }
  render() {
    const { total } = this.state;
    return (
      <>
        <h2>{total}</h2>
        <button onClick={this.increment.bind(this)}>增加</button>
      </>
    );
  }
}
class组件自己封装
import React from "react";
export default class App extends React.Component {
  state = {
    total: 0,
  };
  async increment() {
    await this.setStateAsync({ count: (this.state.total += 1) });
    console.log("自己封装的方法去获取", this.state.total);
  }
  setStateAsync(state) {
    return new Promise(resolve => {
      this.setState(state, resolve);
    });
  }
  render() {
    const { total } = this.state;
    return (
      <>
        <h2>{total}</h2>
        <button onClick={this.increment.bind(this)}>增加</button>
      </>
    );
  }
}
推荐第一个方法获取,尽量不破坏原来的写法。
hook写法示例代码
import React, { useState, useEffect } from "react";
const App = () => {
  const [count, setCount] = useState(0);
  const increment = () => {
    setCount(count + 1);
  };
  useEffect(() => {
    //第二参数里的数组就是要监听的数据
    console.log(count);
  }, [count]);
  return (
    <>
      <h2>{count}</h2>
      <button onClick={increment.bind(this)}>增加</button>
    </>
  );
};
export default App;
useState仅修改对象内某一个值
在使用Hook的函数式组件中,比如我们用useState定义了某一个对象,这个对象的键值不止一个,而我们修改的时候,只想修改某一个键值的数据,我们可以这么做:
定义初始对象:
const [form,setForm] = useState({
	name:"王萌萌",
	age:18,
	sex:'女'
})
方法一:
拿到旧的数据,ES6 结构赋值,附上新的属性,后面的数据覆盖前面的数据(推荐)
setForm((olddata)=>{
	return{
	...olddata,
	age:20
	}
})
方法二:
ES6 解构赋值,后面的数据覆盖前面的数据
setForm({
	...form,
	age:20
})
方法三:
const fn = () => {
    let _form = JSON.parse(JSON.stringify(form))
    _form.age = 20
    setState(_form)
}
