DEV Community

kimbi619
kimbi619

Posted on

How to send data (state and props) between unrelated components in react

Alt Text
If you are new to react, you may have heard that data only flows in one direction as illustrated by the image above. To pass data from a lower level component to its parent or one of it's ancestors, you use something called lifting up state, where data is being moved up to higher components having same parents and passing it down as props.
In React, a state is always owned by one component. Any changes made by this state can only affect the components below it, i.e. its children. Changing state on a component will never affect its parent or its siblings, only the children will be affected. This is the main reason that the state is often moved up in the component tree so that it can be shared between the components that need to access it. However, to have a state affect directly an unrelated component was hard until the useContext Hook was added to react.

Suppose from the image you have an event listener on the component C and you want it to cause a action on A as illustrated above without having to send data to the database and getting that data from there. The answer to your problem is the use context hook in React. I will use the example on a book app I was creating for a library to explain this

import React, {createContext, useState} from 'react'

export const BookHoldContext = createContext();

export const BookHoldProvider = (props)=>{
    const [clickedBook, setClickedBook] = useState(null);

Enter fullscreen mode Exit fullscreen mode

Declaring using the useState method in react, you can create the data that you want to pass to the different components after importing the createContext method in react as in the first line. I have initially set it to null, so that every time an event happens on it you get to set the data to what you currently want to get. Now to return this context, you use the context.Provider as below and pass the state as props in the value, except they are not especially props but return values.
This is still within the provider function declared above

return(
        <BookHoldContext.Provider value={[clickedBook, setClickedBook]}>
            {props.children}
        </BookHoldContext.Provider>
    )
Enter fullscreen mode Exit fullscreen mode

Now to actually consume this context, you need to go to their common parent component and wrap the component you need to provide access to with the Provider tag, after importing it of course import { BookHoldProvider } from './BookHoldContext'
in my case I need to share it between the book item and the book detail

return(
        <div id="book">
            <BookHoldProvider>
            <div className="container">
                <ul className="bookItem">
                    {
                    AllBooks.map((book)=>(
                        <li key={book.isbn} ><Book book={book} 
                         showDetail={showDetail} /></li>
                    ))}
                </ul>
            </div>
            <BookDetail showDetail = {showDetail}/>
            </BookHoldProvider>
        </div>
    )
Enter fullscreen mode Exit fullscreen mode

Finally, on the function you where actually suppose to put that state on, you can import the created context and the useContext method inbuild in React

import {useContext} from 'react';
import {BookHoldContext} from './BookHoldContext';
Enter fullscreen mode Exit fullscreen mode
function BookDetail(){

    const [clickedBook, setClickedBook] = 
    useContext(BookHoldContext);
    return (
        <div className='bookToLoan' >
         {console.log(clickedBook)}
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Inside your component, you can call those values (useState hook) you passed in the context Provider and the data can be used. 🤗

This is actually my first post here guys, I hope it helps someone

Top comments (0)