React hook useEffect всегда перерисовывается при React Navigation - PullRequest
0 голосов
/ 04 марта 2020

При использовании функциональных компонентов, которые являются «страницей» по умолчанию на createSwitchNavigator, после перехода к bottomTabNavigator, если состояние изменяется (не только при изменении условного триггера), весь компонент будет повторно отображаться, вызывая используйте код эффекта для повторного выполнения.

Навигация по маршруту у меня выглядит следующим образом:

const Routes = createAppContainer(
  createSwitchNavigator({
    Sign: createSwitchNavigator({
      Preload,
      SignIn,
    }),
    App: createBottomTabNavigator(
      {
        Home,
        Employees,
      },
    ),
  }),
);

и функциональный компонент, который делает навигацию между SignIn и Home:

const Preload = ({navigation, logged}) => {
    useEffect(() => {
        if (logged) {
            navigation.navigate({routeName: 'Home'});
        } else {
            navigation.navigate({routeName: 'SignIn'});
        }
    }, [logged]);

    return (
        <Container>
            <ActivityIndicator color="#1199DD" size={50}/>
        </Container>
    );
}

также отмечая, что есть соединитель контейнера / страницы для диспетчера действия потока, использующий перехватчики:

const mapDispatchToProps = dispatch => ({
    actions: {
        ...appActions(dispatch),
        dispatch
    },
})

const mapStateToProps = state => ({
    ...state.app
})


export default connect(mapStateToProps, mapDispatchToProps)(Preload)

функция соединения в основном создает запросы, передаваемые потребителю, отправка и состояние моего хранилища:

const isFunction = target => typeof target === 'function'
const defaultMapStateToProps = () => ({})
const defaultMapDispatchToProps = () => ({})

export default appContext => (originalMapStateToProps, originalMapDispatchToProps) => {

    const { Consumer } = appContext

    const mapStateToProps = isFunction(originalMapStateToProps)
        ? originalMapStateToProps
        : defaultMapStateToProps
    const mapDispatchToProps = isFunction(originalMapDispatchToProps)
        ? originalMapDispatchToProps
        : defaultMapDispatchToProps

    return Component => (props) => (
        <Consumer>
            {store => (
                <Component
                    {...props}
                    {...mapStateToProps(store.getState())}
                    {...mapDispatchToProps(store.dispatch)}
                />
            )}
        </Consumer>
    )
}

Я пытался использовать ловушку useRef, чтобы рассмотреть последнее значение, но, поскольку оно перерисовывает все, последнее значение не является доверенным, поскольку оно всегда будет воссоздавать эту переменную.

Что действительно вызывает все перерисовать? И как лучше всего обойти это?

1 Ответ

0 голосов
/ 05 марта 2020

Решением было отказаться от connect / container, который вмещает Потребителя, так как я использую React Hooks, чтобы отправлять действия и состояние, которые ранее были перехвачены диспетчеризацией при инициализации useReducer.

. После этого пример:

const [useContext, Provider] = createRootContext();

function createRootContext() {
    const RootContext = createContext(initialStateCombined);

    function useContext() {
        const c = React.useContext(RootContext);
        if (!c) throw new Error('');
        return c;
    }
    return [useContext, RootContext.Provider];
}

function RootProvider(props) {
    const [state, dispatch] = useReducer(appReducer, appInitialState);

    const actions = {
        app: {...appActions(dispatch)},
    };

    return <Provider value={{ state, actions }}>{props.children}</Provider>;
}

export { useContext, RootProvider };

Поскольку я являюсь моим провайдером (как наивысший родительский элемент приложения), я могу получить доступ ко всему из состояния, импортировав из него useContext, например:

const Preload = ({navigation}) => {
    const { state: { app } } = useContext();

    useEffect(() => {
        if (app.logged) {
            navigation.navigate('Home');
        } else {
            navigation.navigate('SignIn');
        }
    }, [app.logged])

    return (
        <Container>
            <ActivityIndicator color="#1199DD" size={50}/>
        </Container>
    )
}
...