簡體   English   中英

React hooks:在子組件中調用dispatch時,父組件不更新

[英]React hooks: Parent component not updating when dispatch is called in a child component

我一直在遵循使用useContext將reducer傳遞給子組件的指南,但是當從子組件調度時,它似乎沒有重新渲染父組件。

從子組件調度時,狀態本身似乎正在更新(由console.logging state.count完成),但父組件不反映狀態的變化。

我已經嘗試將調度功能作為道具傳遞給Child,這確實更新了App.js,但我認為我的方法更清晰,而我可能做錯了。 我還將{state.count}放在Child.js中,它確實得到了正確的更新,但是對於這種情況,我需要在父組件中。 這是代碼:

App.js

import React, { useReducer } from 'react';
import { StateProvider } from './reducer';
import Child from './Child'

function App() {
    const reducer = (state, action) => {
        switch (action.type) {
            case 'add':
                console.log(state.count+1)
                return {...state, count: state.count + 1}
            default:
                throw new Error();
        }
    }

    const initialState = {count: 1};
    const [state, dispatch] = useReducer(reducer, initialState)

    return (
        <StateProvider initialState={initialState} reducer={reducer}>
            <div className="App">
                {state.count}
                <Child></Child>
            </div>
        </StateProvider>
  );
}

export default App;

reducer.js

import React, {createContext, useContext, useReducer} from 'react';

export const StateContext = createContext(null);

export const StateProvider = ({reducer, initialState, children}) => (
    <StateContext.Provider value={useReducer(reducer, initialState)}>
        {children}
    </StateContext.Provider>
);

export const useStateValue = () => useContext(StateContext);

Child.js

import React from 'react';
import { useStateValue } from './reducer';

export default function Child(props) {
    const [state, dispatch] = useStateValue();

    return (
        <button onClick={() => dispatch({type: 'add'})}>Increment</button>
    )
}

那是因為你在StateProvider中重新創建了一個reducer

<StateContext.Provider value={useReducer(reducer, initialState)}>

相反,只需將實際減速器的dispatch傳遞下去:

<StateProvider initialState={initialState} reducer={{dispatch}}> 

然后使用它:

const StateProvider = ({reducer, initialState, children}) => (
    <StateContext.Provider value={reducer}>
        {children}
    </StateContext.Provider>
);

順便說一句,我認為您可以在組件外部聲明reducer邏輯函數,這樣就無需在每次呈現App重新聲明它。

這是一個運行的例子:

 // mimic imports const {createContext, useContext, useReducer} = React; const StateContext = createContext(null); const StateProvider = ({reducer, initialState, children}) => ( <StateContext.Provider value={reducer}> {children} </StateContext.Provider> ); const useStateValue = () => useContext(StateContext); function Child(props) { const {dispatch} = useStateValue(StateContext); return ( <button onClick={() => dispatch({type: 'add'})}>Increment</button> ) } const reducer = (state, action) => { switch (action.type) { case 'add': console.log(state.count+1) return {...state, count: state.count + 1} default: throw new Error(); } } function App() { const initialState = {count: 1}; const [state, dispatch] = useReducer(reducer, initialState) return ( <StateProvider initialState={initialState} reducer={{dispatch}}> <div className="App"> {state.count} <Child></Child> </div> </StateProvider> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script> <div id="root"/> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM