Заставить отдельный компонент исчезнуть с помощью useReducer - PullRequest
0 голосов
/ 04 марта 2019

В настоящее время я изучаю функцию React Hooks, поэтому я создал небольшой эксперимент, в котором при нажатии кнопки появится невидимое (несмонтированное) поле;если поле видимо и вы щелкаете в любом месте страницы, кроме поля, поле исчезнет.Я изо всех сил пытаюсь заставить коробку исчезнуть, и я не знаю, что вызывает ошибку.

Исходное состояние и редуктор:

const initialState = { visible: false };

const reducer = (state, action) => {
    switch (action.type) {
        case 'show':
            return { visible: true };

        case 'hide':
            return { visible: false };

        default:
            return state;
    }
};

Компонент коробки:

function Box() {
    const [state, dispatch] = useReducer(reducer, initialState);
    const boxElement = useRef(null);
    const boxStyle = {
        width: '200px',
        height: '200px',
        background: 'blue'
    };

    function hideBox(e) {
        if(!boxElement.current.contains(e.target)) {
            dispatch({ type: 'hide' });
        }
    }

    useEffect(() => {
        window.addEventListener('click', hideBox);

        return () => {
            window.removeEventListener('click', hideBox);
        }
    });

    return <div style={boxStyle} ref={boxElement} />
}

Основной:

function App() {
    const [state, dispatch] = useReducer(reducer, initialState);

    function showBox() {
        dispatch({ type: 'show' });
    }

    return (
        <section>
            { state.visible && <Box /> }
            <button onClick={showBox}>Show box</button>
        </section>
    )
}

1 Ответ

0 голосов
/ 04 марта 2019

Вы используете два экземпляра useReducer, в то время как вам нужно иметь только один экземпляр на уровне App component и передать dispatch as a prop to Box, в противном случае вы будете обновлять только состояние, используемое useReducer в Box, а не состояние в App.компонент

function App() {
    const [state, dispatch] = useReducer(reducer, initialState);

    function showBox() {
        dispatch({ type: 'show' });
    }

    return (
        <section>
            { state.visible && <Box dispatch={dispatch}/> }
            <button onClick={showBox}>Show box</button>
        </section>
    )
}

Box.js

function Box({dispatch}) {
    const boxElement = useRef(null);
    const boxStyle = {
        width: '200px',
        height: '200px',
        background: 'blue'
    };

    function hideBox(e) {
        if(!boxElement.current.contains(e.target)) {
            dispatch({ type: 'hide' });
        }
    }

    useEffect(() => {
        window.addEventListener('click', hideBox);

        return () => {
            window.removeEventListener('click', hideBox);
        }
    });

    return <div style={boxStyle} ref={boxElement} />
}

Рабочая демонстрация

...