Skip to content

Commit

Permalink
refactor: make container a function (facebook#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
osdnk authored and satya164 committed Jul 20, 2019
1 parent 77c7315 commit 637263e
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 51 deletions.
107 changes: 57 additions & 50 deletions src/NavigationContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,60 +33,67 @@ export const NavigationStateContext = React.createContext<{
},
});

export default class NavigationContainer extends React.Component<Props, State> {
state: State = {
navigationState: this.props.initialState,
};
export default function NavigationContainer(props: Props) {
const [state, setState] = React.useState<State>({
navigationState: props.initialState,
});

componentDidUpdate(_: Props, prevState: State) {
const { onStateChange } = this.props;
const navigationState = React.useRef<
NavigationState | PartialState | undefined | null
>(null);

if (prevState.navigationState !== this.state.navigationState) {
onStateChange && onStateChange(this.state.navigationState);
}
}

private navigationState:
| NavigationState
| PartialState
| undefined
| null = null;

private performTransaction = (action: () => void) => {
this.setState(
state => {
this.navigationState = state.navigationState;
action();
return { navigationState: this.navigationState };
const {
performTransaction,
getNavigationState,
setNavigationState,
}: {
performTransaction: (action: () => void) => void;
getNavigationState: () => PartialState | NavigationState | undefined;
setNavigationState: (
newNavigationState: NavigationState | undefined
) => void;
} = React.useMemo(
() => ({
performTransaction: action => {
setState((state: State) => {
navigationState.current = state.navigationState;
action();
return { navigationState: navigationState.current };
});
},
() => (this.navigationState = null)
);
};

private getNavigationState = () =>
this.navigationState || this.state.navigationState;
getNavigationState: () =>
navigationState.current || state.navigationState,
setNavigationState: newNavigationState => {
if (navigationState.current === null) {
throw new Error(
'setState need to be wrapped in a performTransaction'
);
}
navigationState.current = newNavigationState;
},
}),
[]
);

private setNavigationState = (
navigationState: NavigationState | undefined
) => {
if (this.navigationState === null) {
throw new Error('setState need to be wrapped in a performTransaction');
const isFirstMount = React.useRef<boolean>(true);
React.useEffect(() => {
navigationState.current = null;
if (!isFirstMount.current && props.onStateChange) {
props.onStateChange(state.navigationState);
}
this.navigationState = navigationState;
};
isFirstMount.current = false;
}, [state.navigationState, props.onStateChange]);

render() {
return (
<NavigationStateContext.Provider
value={{
state: this.state.navigationState,
getState: this.getNavigationState,
setState: this.setNavigationState,
performTransaction: this.performTransaction,
}}
>
<EnsureSingleNavigator>{this.props.children}</EnsureSingleNavigator>
</NavigationStateContext.Provider>
);
}
return (
<NavigationStateContext.Provider
value={{
state: state.navigationState,
getState: getNavigationState,
setState: setNavigationState,
performTransaction: performTransaction,
}}
>
<EnsureSingleNavigator>{props.children}</EnsureSingleNavigator>
</NavigationStateContext.Provider>
);
}
4 changes: 3 additions & 1 deletion src/__tests__/useOnChildUpdate.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ it("lets children handle the action if parent didn't", () => {
],
};

render(
const element = (
<NavigationContainer
initialState={initialState}
onStateChange={onStateChange}
Expand All @@ -101,6 +101,8 @@ it("lets children handle the action if parent didn't", () => {
</NavigationContainer>
);

render(element).update(element);

expect(onStateChange).toBeCalledTimes(1);
expect(onStateChange).lastCalledWith({
index: 0,
Expand Down

0 comments on commit 637263e

Please sign in to comment.