yahoo/react-i13n

Question: createI13nNode with component still causes react 15.2 props warning

Closed this issue · 5 comments

I might be approaching this all wrong but if I try something like this:

import { createI13nNode } from 'react-i13n';
import { NavLink } from 'fluxible-router';

var I13nNavLink = createI13nNode(NavLink, {
    isLeafNode: true,
    bindClickEvent: true,
    follow: false
});

export default I13nNavLink;

And use it like this:

<I13nNavLink i13nModel={{category: 'Homepage', action: 'click', label: 'Skip Tool'}} href="/products" preserveScrollPosition={false} className="link link--inline">Link</I13nNavLink>

The i13n props are passed down to NavLink which results in the error: Unknown props i13n, i13nModel, isLeafNode, bindClickEvent, follow, scanLinks on <a> tag. Remove these props from the element.

I'm I doing something I'm not supposed to do?

Relevant package versions:

    "fluxible": "1.2.0",
    "fluxible-addons-react": "0.2.8",
    "fluxible-router": "^1.0.0-alpha.7",
    "react": "^15.0.0",
    "react-addons-create-fragment": "^15.0.0",
    "react-dom": "^15.0.0",
    "react-i13n": "2.1.2",
    "react-i13n-ga": "0.2.5",

thanks @dasblitz for reporting this, you are doing good, the reason is we only filter the props for native tags, if the createI13nComponent is working on a Component, we just pass through and assume Component will control its render function to get rid of these warnings.

I was thinking we should just provide this filter to Components as well, but this will filter this.props.i13n and generate a breaking change. We should only keep props.i13n, I will make a PR to do this. But there's still props.i13n will be passed into the wrapped Component.

The thing here is NavLink is another special case that it needs to pass whatever attribute to the <a>, so it passes these i13n props as well.

So we are seeing these warning when we combine these two things together. However NavLink do have a optional getFilteredProps to get rid of this issue, we can define whatever we want to filter out. so for example

import { createI13nNode } from 'react-i13n';
import { createNavLinkComponent } from 'fluxible-router';
var NavLink = createNavLinkComponent({
    /* I was pasting wrong blob here at the beginning...
        getDefaultProps: function () {
        // this part can be just i13n if we filter out other attributes
        return {
            bindClickEvent: true,
            follow: false,
            i13n: true,
            i13nModel: null,
            isLeafNode: true,
            model: null,
            scanLinks: null
        };
    }*/
    getFilteredProps: function () {
        return [
            'bindClickEvent',
            'follow', 
            'i13n',
            'i13nModel',
            'isLeafNode',
            'model',
            'scanLinks'
        ];
    }
});
module.exports =  createI13nNode(NavLink);

not ideal but should be able to fix your problem

Hi @kaesonho, thanks for getting into this. I tried the code snippet you provided to create a NavLink component (didn't know about the createNavLinkComponent method before, nice!), but it gives me the same warning :(

main.js:1093 Warning: Unknown propsi13n,i13nModel,isLeafNode,bindClickEvent,follow,scanLinks,modelon <a> tag.

I'll try and look deeper into why it's not working (check how and when getDefaultProps is called) later this week.

My current workaround (basically doing the same as the filter for native tags) is as follows:

import React from 'react';
import { createI13nNode } from 'react-i13n';
import { NavLink } from 'fluxible-router';


class WrappedLink extends React.Component {
    render() {
        const skipProps = [
                                 'i13n',
                                 'i13nModel',
                                 'isLeafNode',
                                 'bindClickEvent',
                                 'follow',
                                 'scanLinks'
                           ];

        const passedProps = {};

        for (var key in this.props) {
            if(this.props.hasOwnProperty(key) && skipProps.indexOf(key) === -1) {
                passedProps[key] = this.props[key];
            }
        }

        return(<NavLink {...passedProps}>{this.props.children}</NavLink>);
    }
}

var I13nNavLink = createI13nNode(WrappedLink, {
    isLeafNode: true,
    bindClickEvent: true,
    follow: false
});

export default I13nNavLink;

Which is hackish and will of course break as soon as the I13Node implementation changes.

Hi @dasblitz , oh that's my bad, it's some copy-paste mistake :(,

should be something like this

import { createI13nNode } from 'react-i13n';
import { createNavLinkComponent } from 'fluxible-router';
var NavLink = createNavLinkComponent({
    getFilteredProps: function () {
        return [
            'bindClickEvent',
            'follow',
            'i13n',
            'i13nModel',
            'isLeafNode',
            'model',
            'scanLinks'
        ];
    }
});
module.exports =  createI13nNode(NavLink);

your workaround will definitely work, too.

@dasblitz we just had a new version, which helps you to fix this issue without the workaround, please check https://github.com/yahoo/react-i13n/releases/tag/v2.3.0

close this one as 2.3.0 addresses this