Hi, has anybody being able to use the new Context API introduce in react 16.3 with react-native-navigation?
I'm having trouble trying to set it up as with react-native-navigation there is no main component where i can manage a state and then render the Context.Provider components, just the Navigation.startSingleScreenApp or similar functions.
Tks in advance for any help you can provide
We use the issue tracker exclusively for bug reports and feature requests. This issue appears to be a general usage or support question. Instead, please ask a question on Stack Overflow with the react-native-navigation tag.
@dcoellarb did u find a solution?
Any solution to this ?
Please update if any solutions :)
I see this as the only related stackoverflow thread:
https://stackoverflow.com/questions/51187582/how-should-the-new-context-api-work-with-react-native-navigator
This is being worked on atm, progress can be tracked in https://github.com/wix/react-native-navigation/issues/3549
any solution to this ..?? please share any docs if so
@fariya12 is this what you are looking for?
https://github.com/wix/react-native-navigation/blob/a003f75fc1902d8006b80fb0e2ad48050aa511b0/playground/src/screens/ContextScreen.js#L1-L46
@ManAnRuck - I found that code too, but it just seems... wrong. Is it not kinda janky to be using a component that sets its state as a context? I thought contexts and hooks were meant to eradicate the need for stateful class components.
I tried the Playground example and it works. But If you for example want to share the same context between two screens in the same stack it will not trigger an update.
For example:
For some reason the Context data change doesn't change automatically.
This is my best take on a shared state, and it goes against all the benefits of react.
import { EventEmitter } from 'events';
import { useEffect, useRef, useState } from 'react';
type CallingFunction = (...args: any) => any;
const emitter = new EventEmitter();
const states = new Map<CallingFunction, any>();
let ids = 0;
export const useSharedState = (
callingFn: CallingFunction,
initialState: any
) => {
const state = useState(
states.has(callingFn) ? states.get(callingFn) : initialState
);
const id = useRef(ids++);
useEffect(() => {
function onUpdate([emittedFn, emittedId, emittedState]: any) {
if (callingFn !== emittedFn || id.current === emittedId) {
// skip update on same id (recursion)
// skip update on different calling functions
return;
}
// update state
state[1](emittedState);
}
emitter.on('change', onUpdate);
return () => void 0 && emitter.off('change', onUpdate);
}, []);
useEffect(() => {
// set the initial state to the map
states.set(callingFn, state[0]);
// call update on all listeners
emitter.emit('change', [callingFn, id.current, state[0]]);
}, [state]);
return state;
};
import React from 'react';
import { useSharedState } from '../hooks/useSharedState';
import React, { createContext, useState } from 'react';
export const CounterContext = createContext({ counter: 0 });
export function CounterProvider({ children }: any) {
const [counter, setCounter] = useSharedState(CounterProvider, 0);
const increment = () => setCounter(count => count + 1);
const decrement = () => setCounter(count => count - 1);
return (
<CounterContext.Provider value={{ counter, increment, decrement }}>
{children}
</CounterContext.Provider>
);
}
To solve this we are going to have to render the Providers before all screens will render and pass the contexts through the reconciler. There is no other way.
Please make this a top priority!
And yeah redux won't cut it.
@birkir Thanks a lot, that looks like a hefty piece of code. I'll try it out for sure to see how it behaves. Shame that you can't use the context in a more react way. It would be ideal for situations where you got a DeviceListScreen -> DeviceScreen -> DeviceSettingsScreen, which could be a pretty common usage for a mobile app without the need for introducing Redux which brings a lot of overhead and boiler-code for such a small app.
I talked with some of the devs about this, and it seems that Redux is the go-to way to share global state within RNN for the time being, but I hope in the future they will maybe have the time to implement Context API as an option as well. 馃槃