I am getting the error ("Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.") when I am trying to use condition which includes Navigate to "/path" (look at the statement in the code).
return (
<>
<Router>
<Navbar bg="dark" variant="dark">
<Container>
<Navbar.Brand to="/">MoviesReviews</Navbar.Brand>
<Nav className="me-auto">
<Link to="/picks">Picks</Link>
<Link to="/critics">Critics</Link>
</Nav>
<Form className="d-flex">
<FormControl
type="search"
placeholder="Search"
className="me-2"
aria-label="Search"
id = "SearchBox"
/>
{redirect === true? (() => (<Navigate to = "/search"/>)) : null}
<Button variant="outline-success" onClick = {() => pressSearch()}>Search</Button>
</Form>
</Container>
</Navbar>
<Routes>
<Route path = "/" element = {<Reviews/>}/>
<Route exact path = "/picks" element = {<Reviews/>}/>
<Route exact path = "/critics" element = {<Critics/>}/>
<Route exact path = "/search" element = {<SearchReviews search = {searchString}/>}/>
</Routes>
</Router>
</>
);
If you look at the Route exact path for "/search", you see that I am actually returning a <Component/>
. I am pretty sure the problem is in the line which contains the condition ({redirect === true? (() => (<Navigate to = "/search"/>)) : null}
).
CodePudding user response:
{redirect === true? (() => (<Navigate to = "/search"/>)) : null}
with the above statement you :
- in
false
case you are returning null. - in
true
case you are trying to render a function.
() => (<Navigate to = "/search"/>)
Hence it is not valid as a react child.
You have to do : {redirect === true ? <Navigate to="/search"/> : null}
as mentioned in comments.
CodePudding user response:
Functions are not valid JSX, they can't be rendered.
If you are conditionally rendering React components there are a couple syntaxes you can use, neither involves using a function.
Using a ternary:
condition ? <Component1 /> : null
{redirect ? <Navigate to="/search" replace /> : null}
This is useful if you need to conditionally render one of two different components, or to return null as a component result.
Using logical AND (
&&
):condition && <Component1 />
{redirect && <Navigate to="/search" replace />}
This is useful if you only need to conditionally render a single component.
If you are conditionally rendering the entire component render result then you should use the first in order to return null as valid JSX.
Suggestion
It would be better to issue an imperative redirect instead of setting any redirect
state. This has the benefit of not requiring an additional React render cycle to effect the change.
Example:
import { useNavigate } from 'react-router-dom';
...
const Component = () => {
const navigate = useNavigate();
...
// logic to replace setting any `redirect` state
if (<condition to redirect>) {
navigate("/search", { replace: true });
}
...
return (
<>
<Router>
<Navbar bg="dark" variant="dark">
<Container>
<Navbar.Brand to="/">MoviesReviews</Navbar.Brand>
<Nav className="me-auto">
<Link to="/picks">Picks</Link>
<Link to="/critics">Critics</Link>
</Nav>
<Form className="d-flex">
<FormControl
type="search"
placeholder="Search"
className="me-2"
aria-label="Search"
id = "SearchBox"
/>
<Button
variant="outline-success"
onClick={pressSearch}
>
Search
</Button>
</Form>
</Container>
</Navbar>
<Routes>
<Route path="/" element={<Reviews />} />
<Route path="/picks" element={<Reviews />} />
<Route path="/critics" element={<Critics />} />
<Route path="/search" element={<SearchReviews search={searchString} />} />
</Routes>
</Router>
</>
);
};