React 学习之 State 续

152 阅读1分钟

从上篇我们知道 state 会通过 setState、setX 创建新对象触发 UI 更新,那么对 state 当中某一个参数更新时其它参数内容会被覆盖吗?

类组件

  • 当 State 里面有 n、m
class App extends React.Component {
  constructor() {
    super();
    this.state = {	// 初始化
      n: 0,
      m: 0
    };
  }
  addN() {
    this.setState({ n: this.state.n + 1 });
    // m 会被覆盖为 undefined 吗?
  }
  addM() {
    this.setState({ m: this.state.m + 1 });
    // n 会被覆盖为 undefined 吗?
  }
  render() {
    return (
      <div className="App">
        n:{this.state.n}		// 读
        <button onClick={() => this.add()}>+1</button>
        m: {this.state.m}		// 读
        <button onClick={() => this.addM()}>m+1</button>
      </div>
    );
  }
}

结果发现并不会覆盖。那真的是这样吗?

  • 当 State 里面有了第二层属性 举个栗子:只修改了 name
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 0,
      user: {
        name: "chili",
        age: 18
      }
    };
  }
  changeUser() {
    this.setState({
      user: {
        name: "tom"
      }
    });
  }
  render() {
    return (
      <div className="App">
        n:{this.state.n}
        name:{this.state.user.name}
        age:{this.state.user.age}
        <button onClick={() => this.changeUser()}>改变 name</button>
      </div>
    );
  }
}

结果发现只修改 name,n 未变,但是 age 置空了?如何解决?

  1. ... 操作符
changeUser() {
    this.setState({
      user: {
        ...this.state.user,		
        name: "jem"
      }
    });
  }
  1. Object.assign
changeUser() {
    const user = Object.assign({}, this.state.user);
    user.name = "jack";
    this.setState({
      // m 和 n 不会被置空
      user: user
    });
  }

函数组件

  • 写法一:两个 State
function App() {
  const [n, setN] = React.useState(0);
  const [m, setM] = React.useState(0);
  return (
    <div className="App">
      n:{n}
      <button onClick={() => setN(n + 1)}>+1</button>
      m:{m}
      <button onClick={() => setM(m + 1)}>+1</button>
    </div>
  );
}

不会互相覆盖互不影响

  • 写法二:不推荐的写法,会被影响即置空
 function App() {
  const [state, setState] = React.useState({
    n: 0,
    m: 0
  });
  return (
    <div className="App">
      n:{state.n}
      <button onClick={() => setState({ n: state.n + 1 })}>n+1</button>
      m:{state.m}
      <button onClick={() => setState({ m: state.m + 1 })}>m+1</button>
    </div>
  );
}

结果发现函数组件的 setX 连第一层属性也不会合并,那么可以通过 ... 操作符解决

总结

  • 类组件的 setState 会自动合并第一层属性
  • 但是不会合并第二层属性
  • 可以通过 Object.assign 或者 ... 操作符解决
  • 函数组件的 setX 不会合并任何一层属性
  • 也可通过 ... 操作符解决changeUser()