Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Context and Next JS

I'm trying to add simple React Context to my app. I create Context in "./components/DataProvider.js" that looks like this:

import React, { Component } from 'react'

const DataContext = React.createContext()

class DataProvider extends Component {
    state = {
        isAddButtonClicked: false
    }

    changeAddButtonState = () => {
        if( this.state.isAddButtonClicked ) {
            this.setState({
                isAddButtonClicked: false
            })
        } else {
            this.setState({
                isAddButtonClicked: true
            })            
        }
    }

    render() {
        return(
            <DataContext.Provider
                value={{
                    isAddButtonClicked: this.state.isAddButtonClicked,
                    changeAddButtonState: () => {
                        if( this.state.isAddButtonClicked ) {
                            this.setState({
                                isAddButtonClicked: false
                            })
                        } else {
                            this.setState({
                                isAddButtonClicked: true
                            })            
                        }
                    }
                }}
            >
                {this.props.children}
            </DataContext.Provider>
        )
    }

}

const DataConsumer = DataContext.Consumer

export default DataProvider
export { DataConsumer }

Which then I added to "./pages/_app.js"

import App, { Container } from 'next/app'

import DataProvider from '../components/DataProvider'

class MyApp extends App {
render () {
    const { Component, pageProps } = this.props
    return (
    <Container>
        <DataProvider>
        <Component {...pageProps} />
        </DataProvider>
    </Container>
    )
}
}

export default MyApp

And consume it in "./components/AddPostButton.js".

import React, {Component} from 'react'
import { DataConsumer } from './DataProvider'

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'

class AddPostButton extends Component {
    render() {
        return (
            <div>
                <DataConsumer>
                    {({ changeAddButtonState }) => (
                        <a onClick={changeAddButtonState}>
                            <FontAwesomeIcon icon={faPlus} color='#fff' />
                        </a>
                    )}
                </DataConsumer>
            </div>

        )
    }

}

export default AddPostButton

But I get this error "Cannot read property 'changeAddButtonState' of undefined". I'm using React 16.7 and NextJS 7.0.2. Don't know what is wrong.

The second question is should I use one Context for everything or just use them as Model in MVC pattern?

like image 816
GeekDaddy Avatar asked Jan 24 '19 20:01

GeekDaddy


People also ask

Can I use React context with Nextjs?

js. Starting from React v16. 3.0 , it is possible to use a new feature named context to pass data throughout the app.

Can I use Context API in next JS?

To pass the state and functions via Context API, we need to wrap the entire app inside AppContext. Provider component where the AppContext is created by us in the previous step. In a Next. js app, we can see file _app.

What is context Nextjs?

React Context, introduced in React 16.3, is a way to share props globally across the React components tree. Some use cases could be managing and passing around user state or a selected theme with the whole of the app without having to manually pass props down to each button through the component tree.

Which state management is best for next JS?

Using the useState Hook for state management in Next. js. One of the most common ways to manage state is with the useState Hook. We will build an application that lets you increase the score by clicking the button.


1 Answers

I fixed it by moving changeAddButtonState to Context Component state so my DataProvider.js now looks like this

import React, { Component } from 'react'

const DataContext = React.createContext()

class DataProvider extends Component {
    state = {
        isAddButtonClicked: false,
        changeAddButtonState: () => {
            if (this.state.isAddButtonClicked) {
                this.setState({
                    isAddButtonClicked: false
                })
            } else {
                this.setState({
                    isAddButtonClicked: true
                })
            }
        }
    }

    render() {
        return(
            <DataContext.Provider
                value={this.state}
            >
                {this.props.children}
            </DataContext.Provider>
        )
    }

}

const DataConsumer = DataContext.Consumer

export default DataProvider
export { DataConsumer }

And then in AddButton component I changed code to look like this

import React, {Component} from 'react'
import { DataConsumer } from './DataProvider'

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faPlus } from '@fortawesome/free-solid-svg-icons'

class AddPostButton extends Component {
    constructor(props) {
        super(props)
    }

    render() {
        return (
            <div>
                <DataConsumer>
                    {(context) => (
                        <a onClick={context.changeAddButtonState}>
                            <FontAwesomeIcon icon={faPlus} color='#fff' />
                        </a>
                    )}
                </DataConsumer>
            </div>

        )
    }

}

export default AddPostButton
like image 173
GeekDaddy Avatar answered Nov 09 '22 18:11

GeekDaddy