Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context API is broken on react 16.6.0+ #21975

Closed
3 tasks done
brunolemos opened this issue Oct 27, 2018 · 2 comments
Closed
3 tasks done

Context API is broken on react 16.6.0+ #21975

brunolemos opened this issue Oct 27, 2018 · 2 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@brunolemos
Copy link
Contributor

brunolemos commented Oct 27, 2018

Environment

React Native Environment Info:
System:
OS: macOS 10.14
CPU: x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
Memory: 31.34 MB / 16.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 8.11.4 - /usr/local/bin/node
Yarn: 1.10.1 - ~/.yarn/bin/yarn
npm: 6.4.1 - /usr/local/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 12.0, macOS 10.14, tvOS 12.0, watchOS 5.0
Android SDK:
Build Tools: 23.0.1, 23.0.3, 24.0.3, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.0, 26.0.1, 26.0.2, 26.0.3, 27.0.0, 27.0.1, 27.0.2, 27.0.3, 28.0.0, 28.0.2, 28.0.3
API Levels: 19, 22, 23, 24, 25, 26, 27, 28
IDEs:
Android Studio: 3.2 AI-181.5540.7.32.5014246
Xcode: 10.0/10A255 - /usr/bin/xcodebuild
npmPackages:
react: 16.6.0 => 16.6.0
react-native: 0.57.4 => 0.57.4
npmGlobalPackages:
react-native-cli: 2.0.1

Description

Context API works on 16.6.0-alpha.8af6728, but the consumers stop updating after upgrading to 16.6.0 or newer. The release notes say to use 16.6.0-alpha.8af6728 at least. Opening this just to make sure it's a known issue and to track this.

On a related note, I was expecting an alpha version with 16.7.0-alpha.0 support to be already available, to be honest. RN is an important react product, we want to play with new features as soon as possible like everyone else. Let me know how we could help.

Reproducible Demo

import React, { Component } from 'react'
import { Platform, StyleSheet, Text, View } from 'react-native'

const MyContext = React.createContext({ count: 0 })

class Provider extends Component {
  state = { count: 0 }

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState(state => ({ count: state.count + 1 }))
    }, 1000)
  }

  componentWillUnmount() {
    clearInterval(this.interval)
  }

  render() {
    return (
      <MyContext.Provider value={this.state}>
        {this.props.children}
      </MyContext.Provider>
    )
  }
}

export default function App() {
  return (
    <Provider>
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <MyContext.Consumer>
          {({ count }) => (
            <>
              <Text>Welcome to React Native!</Text>
              <Text>Count: {count}</Text>
            </>
          )}
        </MyContext.Consumer>
      </View>
    </Provider>
  )
}
@casieber
Copy link

Did a bit of digging on this before coming across your issue. The problem seems to stem from facebook/react@3b7ee26 in which in DEV the context is proxied through to an inner _context property and thus any checks regarding the context in DEV needs to access the true context through context._context.

Where this comes into play with ReactNative is that during the call to propagateContextChange() the actual context object is being compared (===) to the proxy object, when in reality it should be compared to the ._context property on the proxy object.

        // Check if the context matches.
        if (
          dependency.context === context &&
          (dependency.observedBits & changedBits) !== 0
        ) {
          // Match! Schedule an update on this fiber.

context in the above snippet is the true context object, while dependency.context is the proxy object, and thus the equality check fails and no update is scheduled.

The context property on the dependency is set as part of the updateContextConsumer call. In the linked commit above, the original author clearly accounted for this with his change in ReactFiberBeginWork.js. Further this change was propagated over to this repo with change 8325e09(see the specific line here). That all said, that instance of ReactNativeRenderer-dev.js is not the one currently shipped as part of react-native@latest, even though the latest npm version was shipped days after the commit.

I won't pretend to understand the ship process for all of these integrated files, so I'm not sure if maybe a step was missed or if the latest integrate just hasn't reached time to deploy yet, but the schism here between how react handles context and how react-native is now processing it is causing the problem (at least in my case).

@brunolemos
Copy link
Contributor Author

It works since 0.57.5+.

@facebook facebook locked as resolved and limited conversation to collaborators Nov 20, 2019
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Nov 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

3 participants