帮助组件在reactJS中传递数据

时间:2018-04-13 06:41:41

标签: reactjs

我想要一个可以帮助我更轻松地将数据传递给子组件的组件。 这是一个用例:

const Test = () => {
    const data = {
        loginForm: {
            name: "Batman",
            password: "hard password"
        },
        email: "test@gmail.com"
    };

    return (
        <Block data={data}>
            <div>
                <TextBox name="email" />
            </div>

            <form>
                <Block name="loginForm">
                    <div>
                        <TextBox name="name" />
                    </div>

                    <div>
                        <TextBox name="password" />
                    </div>
                </Block>
            </form>
        </Block>
    );
};

TextBox是:

const TextBox = ({ name, data }) => {
    return (
        <div>
            <label>{name}</label>
            <input value={data} />
        </div>
    );
};

Block是我想要的组件。名为='email'的TextBox将接收data = test@gmail.com 。请注意,它根据子组件的 name 属性传递数据。 secord Block将接收data =

{
 name: "Batman",
 password: "hard password"
}

这就是我所做的:

const Block = ({ name, data, children }) => {
    return passDataToChildren(children, data)
}

function passDataToChildren(children, parentData) {
    return React.Children.map(children, (child) => {

        if (typeof(child.type) !== "function") {
            return React.cloneElement(child, {
                children: passDataToChildren(child.props.children, parentData)
            });
        }

        if (!child.props.name) {
            return child;
        }

        return React.cloneElement(child, {
            data: _.get(parentData, child.props.name),
        });

    });
}

有没有其他方法可以实现相同的行为?我可以使用新的上下文API来实现这个吗?

修改

我想要这种行为,因为除了 data 之外,Block还会传递 errors ,这是一个对象,其中包含数据中每个属性的消息数组和更新函数每个孩子。

function passDataToChildren(children, parentProps) {
    return React.Children.map(children, (child) => {

        if (typeof(child.type) !== "function") {
            return React.cloneElement(child, {
                children: passDataToChildren(child.props.children, parentProps)
            });
        }

        if (!child.props.name) {
            return child;
        }

        return React.cloneElement(child, {
            data: _.get(parentProps.data, child.props.name),


            errors: _.get(parentProps.errors, child.props.name),
            onChange: (value, name = child.props.name) => {
                if (parentProps.onChange) {
                    parentProps.onChange(value, parentProps.name + "." + name);
                }
            }
        });

    });
}

所以TextBox是:

const TextBox = ({ name, data, onChange, errors }) => {
    return (
        <div>
            <label>{name}</label>
            <input value={data} onChange={onChange} />
            <span>{errors.toString()}</span>
        </div>
    );
};

我还有另一个组件 FormViewer ,其中包含道具:数据错误 onChange 表单

const form = {
    ["0, 0"]: {
        name: "email",
        renderWith: "TextBox",
    },
    ["1, 0"]: {
        name: "loginForm.name",
        renderWith: "TextBox",
    },
    ["2, 0"]: {
        name: "loginForm",
        renderWith: {
            ["0, 0"]: {
                renderWith: "TextBox",
                name: "password",
                props: { type="password" }
            }
        }
    }
}

FormViewer 将使用 Block 并构建基于 form 属性的接口

0 个答案:

没有答案