简体   繁体   English

React hooks:在子组件中调用dispatch时,父组件不更新

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

I've been following a guide to pass down a reducer to child components with useContext, but when dispatching from a child component, it did not seem to re-render the parent component. 我一直在遵循使用useContext将reducer传递给子组件的指南,但是当从子组件调度时,它似乎没有重新渲染父组件。

The state itself seems to be correctly updating when dispatching from the Child component (as done by console.logging state.count), but the parent component does not reflect the change in state. 从子组件调度时,状态本身似乎正在更新(由console.logging state.count完成),但父组件不反映状态的变化。

I've tried passing down a dispatch function as a prop to Child, and that did update App.js, but I was thinking that my approach was cleaner and I could be doing something wrong instead. 我已经尝试将调度功能作为道具传递给Child,这确实更新了App.js,但我认为我的方法更清晰,而我可能做错了。 I've also put {state.count} in Child.js and it did get updated properly, but for this situation I need it in the parent component. 我还将{state.count}放在Child.js中,它确实得到了正确的更新,但是对于这种情况,我需要在父组件中。 Here is the code: 这是代码:

App.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 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 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>
    )
}

That's because you are re-creating a reducer in StateProvider : 那是因为你在StateProvider中重新创建了一个reducer

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

Instead, just pass the actual reducer's dispatch down: 相反,只需将实际减速器的dispatch传递下去:

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

And then use it: 然后使用它:

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

BTW, i think you could just declare the reducer logic function outside your component so it won't get re-declared on each render of App for no reason. 顺便说一句,我认为您可以在组件外部声明reducer逻辑函数,这样就无需在每次呈现App重新声明它。

Here is a running example: 这是一个运行的例子:

 // 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.

相关问题 更新父组件 state 时反应子组件不重新渲染 - React child component not rerendering when updating parent component state 使用 React Hooks,当我将 prop 从父组件传递给子组件时,子组件中的 prop 未定义 - Using React Hooks, when I pass down a prop from parent to a child component, the prop in the child component is undefined React hooks 子组件 useEffect 在父组件之前先执行 - React hooks child component useEffect executes first, before parent component 从子组件传递时将 state 保存在父组件中 - 用于多个项目(React Hooks) - saving state in Parent component when passed from the child component- for multiple items(React Hooks) 反应子组件更新父组件时出现反模式错误 - Antipattern error when react child component updating parent 反应子组件不更新父状态 - React child component not updating parent state 通过使用React Hooks将输入传递到子组件中来更新输入值 - Updating Input Value with Input Passed Into Child Component with React Hooks 父 state 更改时子组件不更新 - Child component not updating when parent state changes 父更新vuejs时子组件不更新 - Child Component not updating when parent updates vuejs 在 React Native 中从子组件 TextInput 更新父组件状态 - Updating Parent component state from Child component TextInput in React Native
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM