Skip to content

rerenders on RN 0.68 #6

Closed
Closed
@fondakogb

Description

@fondakogb

Hi,
first of all wonderful light implementation of this useful "tool".
I tried this lib with a simple code with a context provider component (PreferencesProvider with value = object with 2 properties: lang and theme), 2 context consumer components that respectively subscribe one of the 2 "context props" (LangConsumer and ThemeConsumer) and the main screen component StubScreen that only subscribe the context setter function.
On react-native 0.64 code works as expected: when I update only one property (ie. lang) it rerender only the context provider and the LangConsumer component, instead on react-native 0.68 the same code rerenders all consumers: LangConsumer, ThemeConsumer and StubScreen too, no caring of which context property I updated.

I guess that the non-documented feature available on React.createContext API which allows us to disable dispatching updates to every component accessing a Context value isn't available anymore on new react-native release...

ENVIRONMENT INFO:

  • macOs 11.6
  • jdk 11.0.6-zulu
  • Android Studio 2020.3.1 patch 4
  • NPM 8.1.4
  • Node.js 17.2.0
  • react-native 0.64.2 (react 17.0.1) & 0.68.0 (react 17.0.2)
  • Android Emulator API 30 + physical device Android 11 (API 30)

Below sample code:

import React, { useState, useCallback } from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
import { createContext, useContextSelection } from 'use-context-selection';

export default App;

// CONTEXT PROVIDER
const PreferencesContext = createContext();
const PreferencesProvider = ({children}) => {
  const [preferences, setPreferences] = useState({theme: 'light', lang: 'it'});
  const contextValue = {preferences, setPreferences};
  console.debug("render: PreferencesProvider");
  return (
    <PreferencesContext.Provider value={contextValue}>
      {children}
    </PreferencesContext.Provider>
  );
};


// CONTEXT CONSUMERS
const LangConsumer = () => {
  const lang = useContextSelection(PreferencesContext, ({preferences}) => preferences.lang);
  console.debug("render: LangConsumer");
  return (
    <Text>Language: {lang}</Text>
  );
}

const ThemeConsumer = () => {
  const theme = useContextSelection(PreferencesContext, ({preferences}) => preferences.theme);
  console.debug("render: ThemeConsumer");
  return (
    <Text>Theme: {theme}</Text>
  );
}

const StubScreen = () => {
  const setPreferences = useContextSelection(PreferencesContext, ({setPreferences}) => setPreferences )
  const toggleTheme = useCallback(
    () => setPreferences(state => ({
      ...state,
      theme: (state.theme === 'light' ? 'dark' : 'light'),
    })),
    []
  );
  const toggleLang = useCallback(
    () => setPreferences(state => ({
      ...state,
      lang: (state.lang === 'it' ? 'en' : 'it')
    })),
    []
  );

  console.debug("render: StubScreen");
  return (
    <View style={styles.stubView}>
      <ThemeConsumer />
      <Button onPress={toggleTheme} title="Change Theme" />
      <LangConsumer />
      <Button onPress={toggleLang} title="Change Language" />
    </View>
  );
}

// ROOT COMPONENT
function App() {
  console.debug("render: App");
  return (
    <PreferencesProvider>
      <StubScreen />
    </PreferencesProvider>
  );
}

// STYLES
const styles = StyleSheet.create({
  stubView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center'
  },
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions