Achref Ben slimene
Achref Ben slimene

Reputation: 13

how to fix Objects are not valid as a React child object promise

I create an eLearning app using react and want to split routes to many users (pupils, teachers, and admins) so I use this method

NewRoute.js

const NewRoute = ({
    component: Component,
    type: type,
    ...rest
}) => (
    <Route
        {...rest}
        render={ async props => {
            console.log(await CT.checkType(type));
            return CT.checkType(type) === false ? (
                <Redirect to='/login' />
            ) : (
                <Component {...props} />
            )
        }
        }
    />
);

checkType.js

export default {
  checkType: async (type) => {
    try{
      const res = await axios.get('/api/check/');
      console.log('api response',res);
      return true
    } catch(err) {
      console.error(err.message);
      return false
    }
  }
}

Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

Upvotes: 0

Views: 3342

Answers (1)

Vencovsky
Vencovsky

Reputation: 31625

Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead

You are getting this error because you are passing an async function to render, wich is a Promise object. You need to pass a React component. This means that this check CT.checkType(type) === false cannot be an async call.

So what you are trying to do is not possible.

If you want to render a component based on a request where is what you need.

You need to state that checks the following:

  • Check if it's loading
  • Check if it's valid or not

So you first set that the route is loading (rendering some Loading component). When the promise is done, you set is loading to false and set if it's valid or not, wich will return Redirect or Component.

I have done a very simple gist for this situation, but the logic is kind of this:

const PrivateRoute = ({ component: Component, ...otherProps }) => {

    const { isAuthenticated, isLoading } = useContext(AuthContext)

    return (
        <Route
            {...otherProps}
            render={props => (
                !isLoading
                    ?
                    (
                        isAuthenticated
                            ?
                            <Component {...props} />
                            :
                            <Redirect to={otherProps.redirectTo ? otherProps.redirectTo : '/signin'} />
                    )
                    :
                    <Loading />
            )}
        />
    )

}

And inside the AuthContext it calls a method that set isAuthenticated and isLoading based on async requests.

Upvotes: 3

Related Questions