Context API は常に混乱を招きます。この API は公式ですが、公式はこの API は将来変更されるとして、開発者にこの API を使用してほしくないと考えています。今こそその変化の時です。新しい API が統合されました。そして、より「ユーザーフレンドリー」に見えます。特に redux または mobx を使用する必要がある場合は、新しい Context API を選択して、よりシンプルな状態管理を実現できます。
新しい API は非常に簡単に使用できます: React.createContext()
により、2 つのコンポーネントが作成されます: React.createContext()
,这样就创建了两个组件:
import {createContext} from 'react'; const ThemeContext = createContext({ background: 'yellow', color: 'white' });
调用createContext
方法会返回两个对象,一个是Provider
,一个是Consumer
。
那个Provider
是一个特殊的组件。它可以用来给子树里的组件提供数据。一个例子:
class Application extends React.Component { render() { <ThemeContext.Provider value={{background: 'black', color: 'white'}}> <Header /> <Main /> <Footer /> </ThemeContext.Provider> } }
上例展示了如何传递“theme” context的。当然这些值可以是动态的(比如,基于this.state
)。
下一步就是使用Consumer
。
const Header = () => { <ThemeContext.Consumer> {(context) => { return ( <p style={{background: context.background, color: context.color}}> Welcome! </p> ); }} </ThemeContext.Consumer> }
如果在render Consumer
的时候没有嵌套在一个Provider
里面。那么就会使用createContext
方法调用的时候设置的默认值。
注意:
Consumer必须可以访问到同一个Context组件。如果你要创建一个新的context,用的是同样的入参,那么这个新建的context的数据是不可访问的。因此,可以把Context当做一个组件,它可以创建一次,然后可以export,可以import。
这个新的语法用了function as child模式(有时也叫做render prop模式)。如果不是很熟悉这个模式,那么推荐你看一下这些文章。
新的API不再要求你声明contextProps
了。
Context传递的数据和Context.Provider
组件的value
属性是一样的。对Provider
数据的修改会引起所有的消费者(consumer)重绘。
参考这个RFC。新的声明周期方法会被引入,而旧的会被废弃。
这一改变主要是为了强制推行最佳实践。你可以看看这篇文章来了解一下为什么这些生命周期方法会变得很诡异。这些最佳模式在React 16的异步绘制模式(Async Mode)下显得非常重要。
要被废弃的方法:
componentWillMount
--使用componentDidMount
代替
componentWillUpdate
--使用componentDidUpdate
代替
componentWillReceiveProps
--使用一个新的方法:static getDerivedStateFromProps
来代替。
不过这些并不会立刻发生,他们可以用到React 16.4。在React 17里将被彻底移除。如果你开启了StrictMode
或者AsyncMode
,可以通过这样的方式来使用,但是会收到警告:
UNSAFE_componentWillMount
UNSAFE_componentWillReceiveProps
UNSAFE_componentWillUpdate
当componentWillReceiveProps
我们需要其他的方式根据props的变动更新state。社区决定引入一个新的static方法来处理这个问题。
什么是静态方法?一个静态方法就是存在于类内,而不是类的实例内的方法。静态方法访问不到this
,并且在声明的时候有static
关键字在前面修饰。
但是,问题来了。既然这个方法没有办法访问this
,那么如何调用this.setState
呢?答案就是,不调用。这个方法直接返回需要更新的state的数据,或者返回null,如果没有什么需要更新的话。
static getDerivedStateFromProps(nextProps, prevState) { if(nextProps.currentRow === prevState.lastRow) { return null; } return { lastRow: nextProps.currentRow, isCrollingDown: nextProps.curentRow > prevState.lastRow } }
调用这个方法和之前调用this.setState
的效果是一样的。只会修改这些返回的值,如果是null的话则不修改state。state的其他值都会保留。
你需要定义初始state的值。无论是在constructor
里,或者是类属性。否则会报警告。
这个方法getDerivedStateFromProps()
会在第一次挂载和重绘的时候都会调用到,因此你基本不用在constructor里根据传入的props来setState
。
如果定义了getDerivedStateFromProps
后,又定义了componentWillReceiveProps
。那么,只有前者会被调用,并且你会收到一个警告。
一般你会使用一个回调来保证某些代码实在state更新之后才被调用的。那么,请把这些代码都移到componentDidUpdate
里。
如果你不喜欢使用static
ComponentName.getDerivedStateFromProps = (nextProps, prevState) => { // Your code here }
createContext
メソッドを呼び出すと 2 つのオブジェクトが返されます。 プロバイダ
、もう 1 つは コンシューマ
です。 🎜🎜その プロバイダ
は特別なコンポーネントです。これを使用して、サブツリー内のコンポーネントにデータを提供できます。例: 🎜import {StrictMode} from 'react' class Application extends React.Component { render() { return ( <StrictMode> <Context.Provider value={{background: 'black', color: 'white'}}> <Header /> <Main /> <Footer /> </Context.Provider> </StrictMode> ); } }
this.state
に基づく)。 🎜🎜次のステップは、Consumer
を使用することです。 🎜rrreee🎜Consumer
をレンダリングするときに Provider
にネストされていない場合。その後、createContext
メソッドの呼び出し時に設定されたデフォルト値が使用されます。 🎜🎜注意: 🎜contextProps
を宣言する必要がなくなりました。 🎜Context.Provider
コンポーネントの value
属性と同じです。 Provider
データを変更すると、すべてのコンシューマが再描画されます。 🎜componentWillMount
-- 🎜componentDidMount
を使用します。 componentWillUpdate
-- 🎜componentDidUpdate
を使用しますcomponentWillReceiveProps
-- 新しいメソッドを使用します: static getDerivedStateFromProps を使用してください。 🎜StrictMode
または AsyncMode
を有効にすると、この方法で使用できますが、次の警告が表示されます: 🎜UNSAFE_componentWillMount
🎜UNSAFE_componentWillReceiveProps
🎜UNSAFE_componentWillUpdate
🎜componentWillReceiveProps
の場合、props の変更に従って状態を更新する他の方法が必要です。コミュニティは、この問題に対処するために新しい静的方法を導入することを決定しました。 🎜🎜静的メソッドとは何ですか?静的メソッドは、クラスのインスタンス内ではなく、クラス内に存在するメソッドです。静的メソッドは this
にアクセスできず、宣言時にメソッドの前に static
キーワードを付けて変更されます。 🎜🎜しかし、ここで問題が発生します。このメソッドには this
にアクセスする方法がないため、this.setState
を呼び出すにはどうすればよいでしょうか?答えは電話しないでくださいです。このメソッドは、更新する必要がある状態データを直接返します。更新するものがない場合は null を返します。 🎜rrreee🎜 このメソッドを呼び出すと、以前に this.setState
を呼び出したのと同じ効果があります。これらの戻り値のみが変更されます。null の場合、状態は変更されません。状態の他のすべての値は保持されます。 🎜constructor
内、またはクラス属性として。それ以外の場合は、警告が報告されます。 🎜🎜このメソッド getDerivedStateFromProps()
は、最初のマウントと再描画中に呼び出されるため、基本的にコンストラクターで受信した props に基づいて setState
を行う必要はありません。 🎜🎜getDerivedStateFromProps
が定義されている場合、componentWillReceiveProps
が定義されます。その後、前者のみが呼び出され、警告が表示されます。 🎜🎜一般的には、状態が更新されるまで特定のコードが呼び出されないようにするためにコールバックを使用します。次に、これらのコードをすべて componentDidUpdate
に移動してください。 🎜🎜 static
キーワードを使用したくない場合は、次のようにすることができます: 🎜ComponentName.getDerivedStateFromProps = (nextProps, prevState) => { // Your code here }
严格模式是一个新的方式来确保你的代码是按照最佳实践开发的。它实际是一个在React.StrictMode
下的组件。它可以用在你的组件树的任何一部分上。
import {StrictMode} from 'react' class Application extends React.Component { render() { return ( <StrictMode> <Context.Provider value={{background: 'black', color: 'white'}}> <Header /> <Main /> <Footer /> </Context.Provider> </StrictMode> ); } }
如果一个在StricMode
子树里的组件使用了componentWillMount
方法,那么你会看到一个报错消息。
异步模式在React.unsafe_AsyncMode
下。使用AsncMode
也会打开StrictMode
模式下的警告。
相关推荐:
以上がReact 16.3 の新機能の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。