简体   繁体   中英

How to change context in Consumer instead of Provider?

I found this question which answers to this problem with adding all context change functions to the topmost parent. React Context api - Consumer Does Not re-render after context changed

But this is awkward, I want the functions that change the context in the components that change it. Let's say I have a button that changes something in the content, I want to have the handleChange() in that component instead of clogging my parent with functions and states that don't belong there.

Is this possible to outsource context logic to components?

If you don't want the parent to have state and state-altering functions, just don't use context - it sounds like local component state is all you are looking for.

context is a just a fancy technique of passing props without worring about hierarchy.

Decoupling the data flow is the only differential when comparing with normal props . So changing the value of a context comes with the some caveats.

When you need to change a shared state between parent and child you need to lift your state up and pass down a way of changing it. With context is no different


Assume the following provider which pass down a theme and a way of chage it

export const context = createContext()
const { Provider } = context

export const ThemeProvider = ({ children }) => {
    const [theme, setTheme] = useState({ color: 'foo' })
    const value = { theme, setTheme }
    return (
        <Provider value={value}>
            {children}
        </Provider>
    )
}

You still need to pass down a handler to change the state. To change theme from inside a Component (which is descendent of ThemeProvider ) you can do like this

import { useContext } from 'react'
import {context} from './ThemeProvider'

const Component = () =>{
    const {theme, setTheme} = useContext(context)

    const handleChange = () => setTheme({color:'blue'})

    return <button onClick={handleChange}>Change</button>
}

Usually (not necessarily) Providers are declared in the top-level component App.js

//App.js
import { ThemeProvider } from './ThemeProvider'

const App = () =>{
    <ThemeProvider>
         <RestOffYourApp />
    </ThemeProvider>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM