8

We have an object 'Schema' with inputs for a form. We map through the inputs and return a custom component for each that then does the rest of the work. The problem is that:

1) Custom components can't have a key attribute, as key is a special property used by React and is not passed to the children.

2) The first item in a list must have a key attribute so that React can know how to update the components.

If your first item in the list is a custom Component, then these two are mutually exclusive. We can get around this problem by surrounding the QuestionBlock with a div or any other generic element and adding a key attribute to it. However this results in code and HTML that looks sloppy, having excessive divs just to work around this problem. Is there any other cleaner way to do it. Below is the code we had before:

render() {
    return (
        <div className="App">
            {Object.keys(Schema.inputs).map((key,index) => {
                let data = Object.assign({}, Schema.inputs[key]);

                data.index = index;

                return <QuestionBlock key={index} {...data} />;
            }}
        </div>
    );
}

Warning shown in console when using the above code:

Warning: QuestionBlock: key is not a prop. Trying to access it will result in undefined being returned. If you need to access the same value within the child component, you should pass it as a different prop.

And below here is the code that works, but looks messy:

render() {
    return (
        <div className="App">
            {Object.keys(Schema.inputs).map((key,index) => {
                let data = Object.assign({}, Schema.inputs[key]);

                data.index = index;

                return <div key={index}>
                            <QuestionBlock {...data} />
                       </div>;
            }}
        </div>
    );
}

Many thanks in advance!

4
  • 1
    It is perfectly valid to put key on a custom component. The only thing I could see causing an issue in your first example is if data contained a key field. Which would overwrite the index value being passed. Commented Jul 19, 2018 at 1:56
  • Technically not an error but a warning. Updated post to show console warning. Commented Jul 19, 2018 at 2:07
  • Are you trying to acces key as prop somewhere in your code? Something like this.props.key anywhere insde QuestionBlock component? Commented Jul 19, 2018 at 2:11
  • No, we're not trying to access the key as a prop at all. Commented Jul 19, 2018 at 2:27

1 Answer 1

9

Instead of wrapping using div, use a keyed Fragment.

Fragment is a container that doesn't generate HTML so it won't clutter your HTML output.

And also you can use a short-hand version <>, not <Fragment>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.