React: Can a higher order component be called in a container component?

In my code base, I have a higher order component (HOC) that I use to add all the input validation functions to this component. It works great when used on a specific component, such as ...

let NameInput = React.createClass({
    render() {
        return (
            <div>
                <label htmlFor="name-input">Name</label>
                <input name="name-input" />
            </div>
        );
    }
});

let NameInput = addInputValidation(NameInput);

module.exports = NameInput;

But now I need to define a series of inputs based on an array from the server. Something like that...

let TestApp = React.createClass({
    render() {
        // Pretend the names array came from the server and is actually an array of objects.
        let names = ['First name', 'Middle name', 'Last name'];

        // Map over our names array in hopes of ending up with an array of input elements
        let nameComponents = names.map((name, index) => {
            let componentToRender = (
                    <div key={index}>
                        <label htmlFor={name}>{name}</label>
                        <input name={name} />
                    </div>
            );

            // Here is where I'd like to be able to use an HOC to wrap my name inputs with validation functions and stuff
            componentToRender = addInputValidation(componentToRender);

            return componentToRender;
        })


        return (
            <div>
                <p>Enter some names:</p>
                {nameComponents}
            </div>
        );
    }
})

let addInputValidation = function(Component) {
    let hoc = React.createClass({
        getInitialState() {
            return {
                isValid: false
            };
        },
        render() {
            return (
                <div>
                    <Component {...this.props} />
                    {this.state.isValid ? null : <p style={{color: "red"}}>Error!!!!</p>}
                </div>
            );
        }
    });

    return hoc;
}

module.exports = TestApp;

I don’t like the reaction when you try to display the result of the HOC call from another component.

I guess this has something to do with mine componentToRenderbeing not really a React component or something.

So my questions are ...

Why can't I call HOC from another component?

Is there a way to call HOC for each element of the array?

jsfiddle, : https://jsfiddle.net/zt50r0wu/

, :

, , , . (, , ..).

addInputValidation HOC , . , Redux, . , . , HOC React.

, ...

let Select = require('components/presentational-form/select');
let Text = require('components/presentational-form/select');
let CheckboxGroup = require('components/presentational-form/select');
let TestApp = React.createClass({
    render() {
        // Pretend the inputs array came from the server
        let inputs = [{...}, {...}, {...}];
        // Map over our inputs array in hopes of ending up with an array of input objects
        let inputComponents = inputs.map((input, index) => {    
            let componentToRender = '';

            if (input.type === 'select') {
                componentToRender = <Select labelText={input.label} options={input.options} />;
            } else if (input.type === 'text') {
                componentToRender = <Text labelText={input.label} />;
            } else if (input.type === 'checkbox') {
                componentToRender = <CheckboxGroup labelText={input.label} options={input.options} />;
            }

            // Here is where I'd like to be able to use an HOC to wrap my name inputs with validation functions and stuff
            componentToRender = addInputValidation(componentToRender, input.validationIndexes);

            return componentToRender;
        })


        return (
            <div>
                <p>Enter some names:</p>
                {inputComponents}
            </div>
        );
    }
})
+4
3

, , , - . . , , , , . , - :

( , BTW, )

let Select = require('components/presentational-form/select');
let Text = require('components/presentational-form/select');
let CheckboxGroup = require('components/presentational-form/select');
let TestApp = React.createClass({
    render() {
        // Pretend the inputs array came from the server
        let inputs = [{...}, {...}, {...}];
        // Map over our inputs array in hopes of ending up with an array of input objects
        let inputComponents = inputs.map((input, index) => {    
            let ComponentToRender;
            let props;            

            if (input.type === 'select') {
                ComponentToRender = addInputValidation(Select);
                props = { labelText: input.label, options: input.options };
            } else if (input.type === 'text') {
                ComponentToRender = addInputValidation(Text);
                props = { labelText: input.label };
            } else if (input.type === 'checkbox') {
                ComponentToRender = addInputValidation(CheckboxGroup);
                props = { labelText: input.label, options: input.options };
            }

            let element = <ComponentToRender {...props} />;

            return element;
        })


        return (
            <div>
                <p>Enter some names:</p>
                {inputComponents}
            </div>
        );
    }
})
+1

: , .map. ,

return componentToRender;

return React.createElement(componentToRender);

:

  • addInputValidation , (<div />).
  • JSX (), .

, - Input , prop:

let Input = React.createClass({
    render() {
        return (
            <div>
                <label htmlFor={this.props.name}>{this.props.name}</label>
                <input name={this.props.name} />
            </div>
        );
    }
});

module.exports = addInputValidation(Input);

let nameComponents = names.map((name, index) => <Input key={index} name={name} />);
+1

, , . HOC - .

, ValueLink .

.

+1

Source: https://habr.com/ru/post/1665790/


All Articles