1

I need to set state on nested object value that changes dynamically Im not sure how this can be done, this is what Ive tried.

const [userRoles] = useState(null);

const { isLoading, user, error } = useAuth0();

useEffect(() => {
    console.log(user);
    // const i = Object.values(user).map(value => value.roles);
    // ^ this line gives me an react error boundary error 
  }, [user]);

// This is the provider
<UserProvider
      id="1"
      email={user?.email}
      roles={userRoles}
>

The user object looks like this:

{
    name: "GGG",
    "website.com": {
      roles: ["SuperUser"],
      details: {}
    },
    friends: {},
    otherData: {}
}

I need to grab the roles value but its parent, "website.com" changes everytime I call the api so i need to find a way to search for the roles.

hernandeΩ
  • 69
  • 1
  • 2
  • 8
  • 1
    It's not clear to me how this is related to React state. It sounds like the goal is to find a way in JavaScript to check an object's properties to see which, if any, contains a property called `roles`. Is that correct? – David Jan 11 '21 at 21:58
  • 1
    Yes thats apart of it but I need to set it to its react state – hernandeΩ Jan 11 '21 at 22:00
  • For the state part you're just missing the `setUserRoles` part of the `useState` call. Look at the examples in [the documentation](https://reactjs.org/docs/hooks-state.html). You'd do something like: `const [userRoles, setUserRoles] = useState(null);` Then within your component any time you want to set that state value you'd call the `setUserRoles` function and pass it the new object. – David Jan 11 '21 at 22:03
  • Where does this user object come from? I suggest that you fix the problem at the object level by making a fixed key like `site` rather than a dynamic key based on the URL. – Code-Apprentice Jan 11 '21 at 22:20

3 Answers3

1

You can search the values for an element with key roles, and if found, return the roles value, otherwise undefined will be returned.

Object.values(user).find(el => el.roles)?.roles;

Note: I totally agree with others that you should seek to normalize your data to not use any dynamically generated property keys.

const user1 = {
    name: "GGG",
    "website.com": {
      roles: ["SuperUser"],
      details: {}
    },
    friends: {},
    otherData: {}
}

const user2 = {
    name: "GGG",
    friends: {},
    otherData: {}
}

const roles1 = Object.values(user1).find(el => el.roles)?.roles;
const roles2 = Object.values(user2).find(el => el.roles)?.roles;

console.log(roles1); // ["SuperUser"]
console.log(roles2); // undefined
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
1

I think you need to modify the shape of your object. I find it strange that some keys seem to be fixed, but one seems to be variable. Dynamic keys can be very useful, but this doesn't seem like the right place to use them. I suggest that you change the shape of the user object to something like this:

{
    name: "GGG",
    site: {
      url: "website.com",
      roles: ["SuperUser"],
      details: {}
    },
    friends: {},
    otherData: {}
}

In your particular use case, fixed keys will save you lots and lots of headaches.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
1

I would recommend what others have said about not having a dynamic key in your data object.

For updating complex object states I know if you are using React Hooks you can use the spread operator and basically clone the state and update it with an updated version. React hooks: How do I update state on a nested object with useState()?

StefanBob
  • 4,857
  • 2
  • 32
  • 38