Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Children in <Link> cause Invariant Violation #143 #1605

Closed
ghost opened this issue Apr 3, 2017 · 14 comments
Closed

Children in <Link> cause Invariant Violation #143 #1605

ghost opened this issue Apr 3, 2017 · 14 comments
Labels
please add a complete reproduction The issue lacks information for further investigation

Comments

@ghost
Copy link

ghost commented Apr 3, 2017

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

fridays/next-routes

Workaround

Router.prefetch

@ghost ghost changed the title Multiple children in <Link> cause Invariant Violation Children in <Link> cause Invariant Violation Apr 3, 2017
@ghost ghost changed the title Children in <Link> cause Invariant Violation Children in <Link> cause Invariant Violation #143 Apr 3, 2017
@ghost
Copy link
Author

ghost commented Apr 4, 2017

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.

@jonaswindey
Copy link
Contributor

jonaswindey commented Apr 6, 2017

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

@ghost
Copy link
Author

ghost commented Apr 6, 2017

@jonaswindey Thanks for the reply Jonas.

Yes, it throws even with a single standard child. There must be something else going on.

@arunoda
Copy link
Contributor

arunoda commented Apr 10, 2017

@flagello can we have a sample repo for that.
I can't re-produce the issue.

@arunoda arunoda added the please add a complete reproduction The issue lacks information for further investigation label Apr 10, 2017
@arunoda
Copy link
Contributor

arunoda commented Apr 10, 2017

Reopen when you add it.

@arunoda arunoda closed this as completed Apr 10, 2017
@wzalazar
Copy link

wzalazar commented Apr 24, 2017

@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>
    );
  }
}

@jonaswindey
Copy link
Contributor

I've seen that error before and restarting the server helped.

@wzalazar: are you also only having the error in production mode?

@jonaswindey
Copy link
Contributor

jonaswindey commented Apr 25, 2017

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.

@jonaswindey
Copy link
Contributor

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.

@wzalazar
Copy link

@jonaswindey you're right, that is the reason of bug :)

@joelburget
Copy link

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...

@jonespen
Copy link
Contributor

@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?

@joelburget
Copy link

@jonespen I didn't take this any further after I figured out my workaround.

@prakharrke
Copy link

prakharrke commented Mar 15, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Mar 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
please add a complete reproduction The issue lacks information for further investigation
Projects
None yet
Development

No branches or pull requests

6 participants