Code
<Link prefetch route='route' params={{param: '1'}}>
<a><span>string</span></a>
</Link>
Error
React.Children.only expected to receive a single React element child.
_Invariant Violation: Minified React error #143_
Environment
Production-only, v2.0.1
Add-on
Workaround
Router.prefetch
Within my environment the error can be reproduced with something as simple as:
// test.js
import Link from 'next/link'
export default props => (
<div>
<Link href='/'>
<a>example</a>
</Link>
</div>
)
import Test from './test'
// render
// ...
<Test />
// ...
Still production-only.
Are you sure you don't have adjacent items in your link?
<Link>
<div>...</div>
<img />
</Link>
for instance, won't work and will give this error message
@jonaswindey Thanks for the reply Jonas.
Yes, it throws even with a single standard child. There must be something else going on.
@flagello can we have a sample repo for that.
I can't re-produce the issue.
Reopen when you add it.
@arunoda , Hi, I have the same issue, this is my component. It's very simple. Only I need repeat a list with routes. Recently, install NextJS version 2.2.0
line: node_modules/next/dist/lib/link.js:174:35
import Link from 'next/link';
import { Component } from 'react';
import PropTypes from 'prop-types';
export default class List extends Component {
static propTypes = {
items: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.any.isRequired,
href: PropTypes.any.isRequired,
})),
}
static defaultProps = {
items: [],
}
render() {
const { items } = this.props;
return (
<ul>
{items.map((item, key) => {
return <li key= { key }>
<Link href= {item.href}> <a>{item.name}</a> </Link>
</li>;
})}
</ul>
);
}
}
I've seen that error before and restarting the server helped.
@wzalazar: are you also only having the error in production mode?
I was able to reproduce the error
<Link prefetch href={{item.href}}><a>{item.name}</a></Link>
works, but
<Link prefetch href={{item.href}}> <a>{item.name}</a> </Link>
doesn't and gives the error you mentioned.
Notice the spaces before and after the <a> tags
@arunoda it seems like React considers the inner spaces as elements (or as null) which throws the error Invariant Violation: React.Children.only expected to receive a single React element child.
Error also occurs with only one space.
It seems like this error is expected behaviour: https://discuss.reactjs.org/t/jsx-newline-bug/3242
Spaces are preserved in JSX so they are considered as child elements.
@jonaswindey you're right, that is the reason of bug :)
I have a scenario where this is pretty inconvenient -- in my blog I parse and render markdown with remark and remark-react, which tends to call <a> with something like ["link text"] as children. This bypasses the if (typeof children === 'string') { check in next/link and then throws at const child = Children.only(children).
I was able to work around in this case with:
function MyLink({ children, href, as }) {
let validChildren = children;
if (Array.isArray(children) && children.length == 1) {
validChildren = children[0];
}
const props = {children: validChildren, href, as};
return <Link {...props} />;
}
... but it would be wonderful if this just worked :)
I'm not sure exactly who's at fault in this case:
remark-react for passing an array? This seems okay to me.react (15.5.4) for throwing on a single-element array? Possibly.next for calling Children.only? It's not clear to me why next calls Children.only...@joelburget I'm having the same issue (I think), but with js-lingui. I'm trying to create a simple example using next.js and js-lingui, but getting the Invariant Violation: React.Children.only expected to receive a single React element child. error when using a Link inside a js-lingui Trans component. All other components works fine. I guess it does something like remark-react.
So, who's to "blame"? Did you figure out anything @joelburget?
@jonespen I didn't take this any further after I figured out my workaround.
My problem got solved by putting a Text tag within the link and then adding the text inside the Text tag.
Instead of,
<Link to="/some-link">Some Link</Link>
Try,
<Link to="/some-link"><Text>Some Link</Text></Link>
Hope this helps.
Most helpful comment
I was able to reproduce the error
works, but
doesn't and gives the error you mentioned.
Notice the spaces before and after the
<a>tags@arunoda it seems like React considers the inner spaces as elements (or as null) which throws the error
Invariant Violation: React.Children.only expected to receive a single React element child.Error also occurs with only one space.