创建<选择>在元素反应JS [英] Creating <select> elements in React JS

查看:209
本文介绍了创建<选择>在元素反应JS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我重写UI为我的web应用程序的react.js,和我有点通过下面的问题难住了。

I'm rewriting the UI for my web-app in react.js, and I'm a bit stumped by the following problem.

我有一个网页,其中显示通过Ajax请求获得的数据,并在下面的是,一个表单提交,显示新的数据。所有优秀的。

I have a page which displays data obtained via an AJAX request, and below that, a form to submit new data is displayed. All good.

现在,我想一个&LT增加;选择> 元素,从不同的位置(URL)的形式,并获取值

Now, I want to add a <select> element to the form, and fetch the values from a different location (url).

目前的code(不包括&LT;选择&GT; )看起来像这样(简化了一下,但所有的工作细节是相同的,它主要是如下在react.js网站上的教程):

The current code (without the <select>) looks like this (simplified a bit, but all the working details are the same; it mostly follows the tutorial on the react.js website):

var tasks_link = $('#tasks_link');

var getDataMixin = {
        loadDataFromServer: function() {
            $.ajax({
                url: this.props.url,
                dataType: 'json',
                success: function(data) {
                    this.setState({data: data});
                }.bind(this),
                error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                }.bind(this)
            });
        },
        getInitialState: function() {
            return {data: []};
        },
        componentDidMount: function() {
            this.loadDataFromServer();
        }
    };

var sendDataMixin = {
        handleDataSubmit: function(senddata) {
            $.ajax({
                url: this.props.url,
                dataType: 'json',
                contentType: 'application/json',
                type: 'POST',
                data: senddata,
                success: function(data) {
                    var curr_d = this.state.data;
                    var curr_d_new = curr_d.concat([data]);
                    this.setState({data: curr_d_new});
                }.bind(this),
                error: function(xhr, status, err) {
                    console.error(this.props.url, status, err.toString());
                }.bind(this)
            });
        }
    };

var taskForm = React.createClass({
        handleSubmit: function() {
            var name = this.refs.task_name.getDOMNode().value.trim();
            if (!name) {
              return false;
            }
            this.props.onTaskSubmit(JSON.stringify({name: name}));
            this.refs.task_name.getDOMNode().value = '';
            return false;
        },
        render: function () {
            return (
                <form className="well base_well new_task_well" onSubmit={this.handleSubmit}>
                    <div className="form-group">
                        <div className="input-group">
                            <span className="input-group-addon no_radius">Task name</span>
                            <input type="text" className="form-control no_radius" id="add_new_project_input" ref="task_name"/>
                        </div>
                    </div>
                    <button type="button" className="btn btn-default no_radius add_button" id="add_new_task_btn" type="submit">Add task</button>
                </form>
            );
        }
    });

var taskBox = React.createClass({
        mixins: [getDataMixin, sendDataMixin],
        render: function () {
            return (
                <div id="project_box" className="taskBox"> <taskList data={this.state.data} />
                    <taskForm onTaskSubmit={this.handleDataSubmit}/> </div>
            );
        }
    });

tasks_link.click(function() {
        React.renderComponent(
            <taskBox url="/api/tasks/" />,
            document.getElementById('content_container')
        );
    });

现在,我可以添加一个选择元素中加入 getDataMixin TaskForm ,获取数据,并建立可能的选项列表,但我需要有形式与许多名单,这一办法似乎并不规模(由于命名冲突,或者我需要使用的东西比其他混入)。

Now, I can add a select element by adding a getDataMixin to TaskForm, fetching the data and building a list of possible options, but I will need to have forms with many lists, and the approach doesn't seem to scale (due to naming collisions; or I'll need to use something other than mixins).

所以,我虽然创建一个单独的阵营类,这只是的 getDataMixin ,获得API网址通过父设置了道具,并呈现&LT;选择&GT; 元素;并使用这个类的表单中。 但我不知道如何访问选定值(因为父母不能访问它的孩子的裁判)。 所以,我需要另一种方式来传递选定值向上。

So I though of creating a separate React class, which would just have the getDataMixin, receive the API url via the parent setting its props, and render the <select> element; and use this class inside the form. But I have no idea how to access the selected value (since a parent cannot access it's child's refs). So I need another way to pass the selected value "up".

或者,如果这是不可能的,在正确的方向轻推 - 我不想落得一吨的非可重复使用的code的原因(部分为什么我转换反应是使用混入并保持code到一个理智和可读性最小)。

Or, in case this isn't possible, a nudge in the correct direction – I don't want to end up with a ton of un-reusable code (part of the reason why I switched to react was to use mixins and keep the code to a sane and readable minimum).

推荐答案

一个家长都可以访问它的孩子的裁判,只要你设置子为父内的裁判,您可以访问子内部的任何参考文献。因此,例如像 this.refs.childRef.refs.nestedChildRef 。然而,这是一个非常糟糕的主意,除非你只是读取信息(和处理错误,如裁判不存在正确的,因为家长不知道孩子的裁判是正确设置)。

A parent can access it's child's refs as long as you set the child as a ref inside the parent, you can access any refs inside that child. So for example something like this.refs.childRef.refs.nestedChildRef. However this is a really bad idea unless you are just reading information (and handling errors such as the refs not existing correctly since the parent doesn't know if the child's ref is set correctly).

但幸运的是有一个非常简单的解决方案。你说得对,你将要创建一个得到它自己的数据,而不是混入一个子组件。但是,你如何处理给选定的项目回父是简单地传递一个onchange功能从父,就像您到内置&LT;选择&GT; 的反应

But luckily there is a very simple solution. You are right, you will want to create a child component which gets it's own data, rather than a mixin. But how you handle giving the selected item back to the parent is simply pass an onChange function from the parent like you would to an in-built <select> in react.

下面是这种父子关系的一个例子:

Here's an example of this parent child relationship:

var MyParent = React.createClass({
    getInitialState: function() {
        return {
            childSelectValue: undefined
        }
    },
    changeHandler: function(e) {
        this.setState({
            childSelectValue: e.target.value
        })
    },
    render: function() {
        return (
            <div>
                <MySelect 
                    url="http://foo.bar"
                    value={this.state.childSelectValue}
                    onChange={this.changeHandler} 
                />
            </div>
        )
    }
});

var MySelect = React.createClass({
    propTypes: {
        url: React.PropTypes.string.isRequired
    },
    getInitialState: function() {
        return {
            options: []
        }
    },
    componentDidMount: function() {
        // get your data
        $.ajax({
            url: this.props.url,
            success: this.successHandler
        })
    },
    successHandler: function(data) {
        // assuming data is an array of {name: "foo", value: "bar"}
        for (var i = 0; i < data.length; i++) {
            var option = data[i];
            this.state.options.push(
                <option key={i} value={option.value}>{option.name}</option>
            );
        }
        this.forceUpdate();
    },
    render: function() {
        return this.transferPropsTo(
            <select>{this.state.options}</select>
        )
    }
});

上面的例子显示了一个父组件 MyParent 包括一个子组件 MySelect ,它通过一个URL来,沿与任何其他道具的有效期为一个标准的反应&LT;选择&GT; 元素。利用反应的内置 this.transferPropsTo()功能在传输的所有道具给孩子的&LT;选择&GT; 元素它的渲染功能。

The above example shows a parent component MyParent including a child component MySelect which it passes a url to, along with any other props that are valid for a standard react <select> element. Using react's built in this.transferPropsTo() function to transfer all props over to the child's <select> element in it's render function.

这意味着父定义 changeHandler 的onChange 处理程序 MySelect 直接通过此功能可将孩子的&LT;选择&GT; 元素。因此,当选择的变化,该事件被父而不是子处理。顺便说一句,这是一个prefectly做的事情作出反应的法律和合法的方式 - 因为它依然遵循自上而下的理念。如果你想想看,当你用一个正常的内置&LT;选择&GT; 的反应,这就是正在发生的事情。 的onChange &LT只是一个属性;选择&GT;

This means that the parent defining changeHandler as the onChange handler for MySelect passes this function directly to the child's <select> element. So when the select changes, the event gets handled by the parent instead of the child. And by the way this is a prefectly legal and legit way to do things in React - since it's still following the top down philosophy. If you think about it, when you use a normal built-in <select> from react, this is exactly what's going on. onChange is just a property for <select>.

另外值得一提的是,如果你愿意,你可以在hyjack的转变处理程序来添加自己的定制逻辑。比如我倾向于做的是总结我的&LT;输入类型=文本/&GT; 与自定义输入组件,接受任何及所有有效<$ C $领域C>&LT;输入&GT; 道具,但也需要验证的功能属性,让我定义一个函数,根据返回的true / false输入到值&LT;输入&GT; 字段。我可以在父定义的onChange ,用于包装的孩子做到这一点,但在孩子我定义自己的的onChange 在内部它检查 this.props.onChange 来定义,而一个函数,然后运行我的验证,并通过调用<$传递事件链备份到父C $ C> this.props.onChange(即有效)。给父母非常相同的事件对象,在它的的onChange 处理程序,还带有一个额外的布尔有效参数。反正,我离题了......

It's also worth noting that if you like, you can "hyjack" the change handler to add your own custom logic. For example what I tend to do is wrap my <input type="text" /> fields with a custom input component that takes any and all valid <input> props, but also takes validator function as a property which allows me to define a function that returns true/false based on the value inputted in to the <input> field. I can do this by defining onChange in the parent, for the wrapper child, but then in the child I define my own onChange internally which checks for this.props.onChange to be defined, and a function, then runs my validator and passes the event chain back up to the parent by calling this.props.onChange(e, valid). Giving the parent the very same event object in it's onChange handler, but also with an added boolean valid argument. Anyway, I digress....

希望这可以帮助你:)

这篇关于创建&LT;选择&GT;在元素反应JS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆