Skip to content

Commit 637263e

Browse files
osdnksatya164
authored andcommitted
refactor: make container a function (facebook#13)
1 parent 77c7315 commit 637263e

File tree

2 files changed

+60
-51
lines changed

2 files changed

+60
-51
lines changed

src/NavigationContainer.tsx

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,60 +33,67 @@ export const NavigationStateContext = React.createContext<{
3333
},
3434
});
3535

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

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

44-
if (prevState.navigationState !== this.state.navigationState) {
45-
onStateChange && onStateChange(this.state.navigationState);
46-
}
47-
}
48-
49-
private navigationState:
50-
| NavigationState
51-
| PartialState
52-
| undefined
53-
| null = null;
54-
55-
private performTransaction = (action: () => void) => {
56-
this.setState(
57-
state => {
58-
this.navigationState = state.navigationState;
59-
action();
60-
return { navigationState: this.navigationState };
45+
const {
46+
performTransaction,
47+
getNavigationState,
48+
setNavigationState,
49+
}: {
50+
performTransaction: (action: () => void) => void;
51+
getNavigationState: () => PartialState | NavigationState | undefined;
52+
setNavigationState: (
53+
newNavigationState: NavigationState | undefined
54+
) => void;
55+
} = React.useMemo(
56+
() => ({
57+
performTransaction: action => {
58+
setState((state: State) => {
59+
navigationState.current = state.navigationState;
60+
action();
61+
return { navigationState: navigationState.current };
62+
});
6163
},
62-
() => (this.navigationState = null)
63-
);
64-
};
65-
66-
private getNavigationState = () =>
67-
this.navigationState || this.state.navigationState;
64+
getNavigationState: () =>
65+
navigationState.current || state.navigationState,
66+
setNavigationState: newNavigationState => {
67+
if (navigationState.current === null) {
68+
throw new Error(
69+
'setState need to be wrapped in a performTransaction'
70+
);
71+
}
72+
navigationState.current = newNavigationState;
73+
},
74+
}),
75+
[]
76+
);
6877

69-
private setNavigationState = (
70-
navigationState: NavigationState | undefined
71-
) => {
72-
if (this.navigationState === null) {
73-
throw new Error('setState need to be wrapped in a performTransaction');
78+
const isFirstMount = React.useRef<boolean>(true);
79+
React.useEffect(() => {
80+
navigationState.current = null;
81+
if (!isFirstMount.current && props.onStateChange) {
82+
props.onStateChange(state.navigationState);
7483
}
75-
this.navigationState = navigationState;
76-
};
84+
isFirstMount.current = false;
85+
}, [state.navigationState, props.onStateChange]);
7786

78-
render() {
79-
return (
80-
<NavigationStateContext.Provider
81-
value={{
82-
state: this.state.navigationState,
83-
getState: this.getNavigationState,
84-
setState: this.setNavigationState,
85-
performTransaction: this.performTransaction,
86-
}}
87-
>
88-
<EnsureSingleNavigator>{this.props.children}</EnsureSingleNavigator>
89-
</NavigationStateContext.Provider>
90-
);
91-
}
87+
return (
88+
<NavigationStateContext.Provider
89+
value={{
90+
state: state.navigationState,
91+
getState: getNavigationState,
92+
setState: setNavigationState,
93+
performTransaction: performTransaction,
94+
}}
95+
>
96+
<EnsureSingleNavigator>{props.children}</EnsureSingleNavigator>
97+
</NavigationStateContext.Provider>
98+
);
9299
}

src/__tests__/useOnChildUpdate.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ it("lets children handle the action if parent didn't", () => {
8181
],
8282
};
8383

84-
render(
84+
const element = (
8585
<NavigationContainer
8686
initialState={initialState}
8787
onStateChange={onStateChange}
@@ -101,6 +101,8 @@ it("lets children handle the action if parent didn't", () => {
101101
</NavigationContainer>
102102
);
103103

104+
render(element).update(element);
105+
104106
expect(onStateChange).toBeCalledTimes(1);
105107
expect(onStateChange).lastCalledWith({
106108
index: 0,

0 commit comments

Comments
 (0)