Hacker News new | past | comments | ask | show | jobs | submit login

It's kind of an abstract problem to describe without code examples or without diving pretty deep into React, but let me see if I can just make something up without getting too far in the weeds. Imagine you're trying to make a ModelUpdateForm component that you can just drop in, which manages all its own state:

  var ProfileUpdateForm = React.createClass({
    render: function() {
      return <ModelUpdateForm model={@props.user}>
        // I don't actually have a reference to `form`.
        // I can't have a reference to `form`.
        // But I need to link state between the ModelUpdateForm and its inputs.
        // Anyway, this is never going to work.
        <ModelInput type="text" valueLink={form.modelValueLink("name")} />
      </ModelUpdateForm>;
    }
  });
Weird workaround that I'm not sure is an officially sanctioned way to deal with it and fear might break in future React versions or have unintended consequences:

  var ProfileUpdateForm = React.createClass({
    render: function() {
      return <ModelUpdateForm
        model={@props.user}
        do={function(form) {
          // Instead of taking children, ModelUpdateForm takes a `do` function prop.
          // It passes itself to `do` which give you a reference to which you can link its inputs.
          return <div>
            <ModelInput type="text" valueLink="form.modelValueLink("name")} />
          </div>;
        }}
      />;
    }
  });
Another idea I've been kicking around and haven't tried would be to create some sort of linker object. Here's the hypothetical end result:

  var ProfileUpdateForm = React.createClass({
    render: function() {
      var valueLinker = new ModelUpdateForm.ValueLinker()
      return <ModelUpdateForm model={@props.user} valueLinker={valueLinker}>
        <ModelInput type="text" valueLink={valueLinker.linkState("name")} />
      </ModelUpdateForm>;
    }
  });
tl;dr - The way React typically wants you to do things, ProfileUpdateForm would have to manage the state. But what I wanted to build was a reusable model-bound form component. If I have to write a lot of model-binding code every time I write a new form, then there's no point to trying to make a reusable component at all. So you start having to try weird-ish ways to get it to become feasible.



It looks like this could make use of React's context feature once #2112 [1] lands.

I have similarish form components [2] which need to do this the hacky way in the meantime (cloning [3] their children in order to pass the form prop they need all the way down):

    <forms.RenderForm form={ProductForm} initial={this.props.product} ref="productForm">
      <Container>
        <Row>
          <Field name="productName" md="8"/>
          <Field name="tags" md="4"/>
        </Row>
        ...

[1] https://github.com/facebook/react/issues/2112

[2] https://github.com/insin/newforms-bootstrap

[3] http://facebook.github.io/react/docs/clone-with-props.html


So are you traversing the entire tree of children here? I'm familiar with cloneWithProps, but I've been wary about this technique because of how deep the components I actually want to bind could be and how much traversal it could take to find them.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: