React 16.3快要发布了,新的context API有望替代redux?
发布于 7 年前 作者 dislido 10117 次浏览 来自 分享

AV(}EZ[~3SZ2MZZ04]D8%4B.png 目前可以试用alpha版本,正式版会在近期发布

{
  "dependencies": {
    "react": "^16.3.0-alpha.0",
    "react-dom": "^16.3.0-alpha.0"
  }
}

新的context

context这个特性已经存在很久了,但因为一些原因一直是处于试验性质的API。 Y`FREBA{_39OOL4_LT)HNX6.png React 16.3带来了正式版的context API

  • createContext创建一个context,context里有ProviderConsumer两个组件
import React, { createContext } from 'react';

const ctx = createContext({
  text: 'hello world!',
});
const { Provider, Consumer } = ctx;

Provider组件用于将context数据传给该组件树下的所有组件 value属性是context的内容

class App extends React.Component {
  render() {
    return (
      <Provider value={{ text: 'hello react!' }}>
        <Comp1 />
        <Comp2 />
      </Provider>
    );
  }
}

要使用context的数据,我们需要使用Consumer组件

// 函数式
const Comp1 = () => (
  <Consumer>
    {context => <p>{context.text}</p>}
  </Consumer>
);
// 类
class Comp2 extends React.Component {
  render() {
    return (
      <Consumer>
        {context => <p>{context.text}</p>}
      </Consumer>
    );
  }
}

可以发现Consumer使用了将一个函数作为它的children的新语法,从上面的例子中可以看出它接收context并将context.text渲染出来
Consumer下不能写其它的东西,比如<Consumer>text: {context => <p>{context.text}</p>}</Consumer>
另外,在新的context API下,我们不需要写contextProps就能使用context了

等等,既然context的内容是写在Provider的value中,那我们创建context时的参数呢? 如果你没有将Consumer作为Provider的子组件,那么Consumer将使用创建context时的参数作为context

更新context

更新context很容易

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text: 'hello react!',
    };
  }
  updateCtx() {
    this.setState({ text: 'updated!' });
  }
  render() {
    return (
      <Provider value={this.state}>
        <button onClick={() => this.updateCtx()}>update</button>
        <Consumer>
          {context => <p>{context.text}</p>}
        </Consumer>
      </Provider>
    );
  }
}

新的context提供了一个简洁的管理全局状态的方式,或许可以替代Redux之类的状态管理库?

生命周期相关改动

为了支持未来的异步渲染特性,以下生命周期函数将被废弃

  • componentWillMount 请使用 componentDidMount代替
  • componentWillUpdate 请使用 componentDidUpdate代替
  • componentWillReceiveProps 请使用新增的 static getDerivedStateFromProps代替
    废弃警告会在React 16.4开启,废弃的函数预计在React 17.0移除

static getDerivedStateFromProps

作为被废弃的componentWillReceiveProps的替代,React提供了一个新的函数static getDerivedStateFromProps(nextProps, prevState)
注意前面的static,这意味着在这个函数中我们不能使用this, 该函数的返回值将用于更新state。如果不需要更新state,就返回null

static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.text === prevState.text) return null;
  return { text: nextProps.text }; // 相当于setState({ text: nextProps.text });
}

严格模式和异步模式

import React, { StrictMode } from 'react';
// ...
<StrictMode>
  // ...
</StrictMode>

当你在严格模式下使用了不建议的函数,你会得到一个警告信息 image.png 同样的unsafe_AsyncMode现在暂时没有用,用于未来的异步渲染

6 回复

看到一篇文章说,其实现在 Redux 使用的就是 这个 context API.
按照示例来理解, 在一个应用中可以创建多个 context, 对应Redux,实际就是一个只用了一个context(state tree). 对应的 flux 构架应该就是可以使用多个context(多个 store).

@phpsmarter 不是redux使用这个api,是react-redux使用的

生命周期相关改动,不理解啊 「 componentWillUpdate 请使用 componentDidUpdate代替 」 意思都不一样啊

@hi363138911 像这样改写

componentWillUpdate(nextProps, nextState) {
  foo(nextProps, nextState);
  bar(this.props, this.state);
  nextProps.a === this.props.a;
}

componentDidUpdate(prevProps, prevState) {
  foo(this.props, this.state);
  bar(prevProps, prevState);
  this.props.a === prevProps.a;
}

context其实以前也一直有用,甚至还有自己实现的context为了防止被官方弃用了。 现在官方正式接受了倒也是好事。 不过和redux比的话,目前感觉他们方式还是有区别的,redux相关实践也算是比较成熟了

回到顶部