mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-25 21:15:26 +08:00
feat: add a setParams method to update route params
This commit is contained in:
@@ -23,9 +23,21 @@ export default function SceneView(props: Props) {
|
||||
const navigation = React.useMemo(
|
||||
() => ({
|
||||
...helpers,
|
||||
setParams: (params: object) => {
|
||||
const state = getState();
|
||||
|
||||
setState({
|
||||
...state,
|
||||
routes: state.routes.map(r =>
|
||||
r.key === route.key
|
||||
? { ...r, params: { ...r.params, ...params } }
|
||||
: r
|
||||
),
|
||||
});
|
||||
},
|
||||
state: route,
|
||||
}),
|
||||
[helpers, route]
|
||||
[getState, helpers, route, setState]
|
||||
);
|
||||
|
||||
const getCurrentState = React.useCallback(() => {
|
||||
|
||||
@@ -1,23 +1,38 @@
|
||||
import * as React from 'react';
|
||||
import { render } from 'react-native-testing-library';
|
||||
import { render, act } from 'react-native-testing-library';
|
||||
import Screen from '../Screen';
|
||||
import NavigationContainer from '../NavigationContainer';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import { Router } from '../types';
|
||||
|
||||
const MockRouter: Router<{ type: string }> = {
|
||||
getInitialState({ screens, initialRouteName }) {
|
||||
getInitialState({ screens, partialState, initialRouteName }) {
|
||||
const routeNames = Object.keys(screens);
|
||||
|
||||
return {
|
||||
key: 'root',
|
||||
names: routeNames,
|
||||
index: routeNames.indexOf(initialRouteName || routeNames[0]),
|
||||
routes: routeNames.map(name => ({
|
||||
key: name,
|
||||
name,
|
||||
})),
|
||||
};
|
||||
let state = partialState;
|
||||
|
||||
if (state === undefined) {
|
||||
const index = routeNames.indexOf(initialRouteName || routeNames[0]);
|
||||
|
||||
state = {
|
||||
index,
|
||||
routes: routeNames.map(name => ({
|
||||
name,
|
||||
key: name,
|
||||
params: screens[name].initialParams,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
if (state.names === undefined || state.key === undefined) {
|
||||
state = {
|
||||
...state,
|
||||
names: state.names || routeNames,
|
||||
key: state.key || 'root',
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
},
|
||||
|
||||
getStateForAction(state, action) {
|
||||
@@ -350,6 +365,65 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('updates route params with setParams', () => {
|
||||
expect.assertions(4);
|
||||
|
||||
const TestNavigator = (props: any) => {
|
||||
const { navigation, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return descriptors[
|
||||
navigation.state.routes[navigation.state.index].key
|
||||
].render();
|
||||
};
|
||||
|
||||
let setParams: (params: object) => void = () => undefined;
|
||||
|
||||
const FooScreen = (props: any) => {
|
||||
setParams = props.navigation.setParams;
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const onStateChange = jest.fn();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer onStateChange={onStateChange}>
|
||||
<TestNavigator initialRouteName="foo">
|
||||
<Screen name="foo" component={FooScreen} />
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
|
||||
act(() => setParams({ username: 'alice' }));
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
index: 0,
|
||||
key: 'root',
|
||||
names: ['foo', 'bar'],
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo', params: { username: 'alice' } },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
],
|
||||
});
|
||||
|
||||
act(() => setParams({ age: 25 }));
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(2);
|
||||
expect(onStateChange).lastCalledWith({
|
||||
index: 0,
|
||||
key: 'root',
|
||||
names: ['foo', 'bar'],
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo', params: { username: 'alice', age: 25 } },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if navigator is not inside a container', () => {
|
||||
expect.assertions(1);
|
||||
|
||||
|
||||
@@ -144,6 +144,12 @@ export type NavigationProp<
|
||||
(ParamList[RouteName] extends void
|
||||
? never
|
||||
: { params: ParamList[RouteName] });
|
||||
|
||||
/**
|
||||
* Update the param object for the route.
|
||||
* The new params will be shallow merged with the old one.
|
||||
*/
|
||||
setParams(params: ParamList[RouteName]): void;
|
||||
};
|
||||
|
||||
export type CompositeNavigationProp<
|
||||
|
||||
Reference in New Issue
Block a user