0

Below example works but how do I do to destructure the useContext data so that, I dont have to map in every div for every array value. I think is not clean at all. Doing it with props I know, I can map while creating the child2 component but I've tried couple ideas with useContext but not luck. Thanks in advance.

function App() {
  return (
    <div className="App">
      <UserDataProvider>
        <Child1 />
      </UserDataProvider>
    </div>
  );
}    

export default function child1() {
    return (
        <div>
            <Child2 />
        </div>
    )
}
    

export default function Child2() {
    const [userData, setUserData] = useContext(UserDataContext)

    return (
        <div>
            <div>
                {userData.map((val, index) => {
                    return (
                        <h1 key={val.id}>{val.name}</h1>
                    )
                })}
            </div>

            <div>diplay phoneNumber</div>

            <div>diplay cardNumber</div>
        </div>
    )
}   


export const UserDataContext = createContext();

const UserDataProvider = (props) => {
    const [userData, setUserData] = useState([{
        id: '1',
        name: 'PersonName',
        phoneNumber: '555555',
        cardNumber: '1234'
    }])

    return (
        <UserDataContext.Provider value={[userData, setUserData]}>
            {props.children}
        </UserDataContext.Provider>
    )
}

export default UserDataProvider
3
  • I guess you could return each individual value and pass them as the values provided to the context provider but it's my assumption your userData will be larger than that. I don't really see anything wrong with mapping through your context as needed for each specific value. You could also convert it to an object Commented Apr 9, 2021 at 20:40
  • Is userData always an array with just one entry? Commented Apr 9, 2021 at 20:41
  • userData is just the way I found to return it so, when I need to update the data the setUserData is there to do so. Commented Apr 10, 2021 at 6:28

1 Answer 1

1

One option I see if you're trying to prevent using an exclusive component is to use useMemo for your resulting rendered array. You could add this to the UserDataProvider:

const userElements = React.useMemo(() => {
  return userData
    ? userData.map(val => (<h1 key={val.id}>{val.name}</h1>))
    : []
}, [userData])

Then add userElements to the returned value properties in the context provider. I would suggest using an object for context value and not returning any variables you don't need to expose (such as userData and setUserData, at least for the example given):

<UserDataContext.Provider {...props} value={{userElements}}/>

The userElements would be passed into your component the same as exposing any property, i.e. <>{userElements}</>

Note that the way I'm using "useMemo" is just a way to skirt around writing a functional React component even though it is essentially doing the same thing. The main difference is you must specify the useMemo dependencies as the second argument explicitly to prevent unnecessary rerendering whereas a simple React component handles this natively given the supplied props (also assuming you don't add any unnecessary props to said component to cause it to rerender more than necessary).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.