简体   繁体   中英

Separating HTML to be rendered in React.js

I'm evaluating the addition of react.js into a new web project that we're about to start. So far I'm loving the data-centric approach (feels a tiny bit like MVVM in that to update the view you do it indirectly by changing the data/state of your object, and then the view knows to represent that new state). I have a few concerns, one of which I'd like to get some feedback on here, since I'm trying to put together a set of standards for coding on this project.

I would like to land on a pattern/norm where we try to declare our visual output/HTML in such a way that it's called out and explicit. I feel that to make this easy enough to maintain you need to be able to browse one of these JSX files (I'm relying on JSX) and see what the basic output is going to be rather quickly. I'd also like for the maintenance or the markup to be as distinct a task as possible from any logic employed to build it.

So I've been trying to split out conditional markup 'chunks' into variables inside the render method - before the return statement - and then in-line them inside the main markup. I was hoping that I could employ the JSX markup hybrid trick (er, my name obviously... still unsure about the lexicon for all these new concepts) anywhere I wanted to, like so:

var sIcon = (<i className='alert-success'></i>);

And then later, something like:

<input type='tel' id="userPhone" onChange={this._handleInputChange('userPhone')} />{sIcon}

So I was hoping to employ the ' (....)' to create in-line HTML and store that in a variable (since it has the advantage of being formatted as HTML in the IDE and stands out better), and later output it using the braces. To me it's more clear that this is output and I prefer it to "React.DOM.div", etc. Nothing at all is rendered, however, it just ignores the ' {sIcon} ' altogether when rendering.

Is this possible? Am I just lousing up the syntax of it?

Or is there another way others have devised to achieve greater HTML/logic separation in react components that I should try out?

It's specifically failing when I declare a variable inside the render method, but initialize it to null and then conditionally try to set it later. So simply declaring a variable with JSX and then referring to it works, but declaring one with no value and then trying to assign JSX to it fails:

  var authorizedBlock = "";
  var sessionIdBlock = "";
  var eventCountBlock = "";
  var sIcon = "";

  var tempIcon = <i className='fa fa-check-square-o' />;
  var tempIcon2;

  if (this.state.loginAttempted) {
     if (this.state.loginSuccessful) {
        authorizedBlock = React.DOM.div (null, "Success! Ye be logged in.");
        sessionIdBlock = React.DOM.div (null, "SessionId: " + this.state.sessionId);
        eventCountBlock = React.DOM.div(null, "Your events: " + this.state.userEventCount);
        tempIcon2 = <i className='fa fa-check-square-o' />;
     }
  };

  return (
  <div id='loginContainer'>
     <div className='row'>
        <div className='col-md-2'>
           Phone:
        </div>
        <div className='col-md-2'>
           <div>
              <input type='tel' id="userPhone" onChange={this._handleInputChange('userPhone') } />
              {tempIcon}{tempIcon2}
           </div>
           {attemptedBlock}
        </div>
        <div className='col-md-1'>
           <button onClick={this._requestCode} >Get code</button>
        </div>
     </div>
</div>);

Note that may HTML may not be utterly well-formed here; it's a partial snippet and I didn't want to include the whole honking file, so forgive any copy/paste gaffs. But the point here is that given the above code, tempIcon will show up in the output but tempIcon2 will not.

Because JSX is nothing more than specially compiled Javascript, saving your JSX to the sIcon variable and then outputting it with {sIcon} should actually work. Make sure you are declaring the variable within render() but not within the actual return statement. Also in the example you provided, there are just empty <i></i> tags so nothing would show up anyway - add some data between those tags and then see what you get.

Working jsFiddle of that

Even though you now know that you can do that, the question remains - should you? I would answer "no". If you find yourself with JSX that you feel really deserves to be separated from the other JSX, you should make a separate child component for that JSX. You can pass down any data needed from the parent component to the child component. Then you will have a clearly named component in your parent that makes the code much more readable and maintainable.

For instance, you could save your JSX to a new child component called <Message /> and pass some data to it, which it then would render. For example, you could have something like this for the parent:

var App = React.createClass({
    render: function() {
        var customData = 'Hello there'; //should come from props or state
        return (<div>
                  <p>Here is some text from the parent</p>
                            <Message data={customData} />
                </div>);
    }
});

And then you would render whatever you wanted your message to look like, for example:

var Message = React.createClass({
    render: function() {
        return <i className='alert-success'>{this.props.data}</i>;
    }
});

jsFiddle

Obviously in this example, the amount of JSX is so small that this might seem like overkill. But once your project starts to scale, this works out wonderfully. Remember, your child components can also have child components and it can continue branching out from there. You'll begin to find that a lot of your components are reusable all over the place, which means you're writing less JSX than you would have otherwise and that your JSX becomes this tree of very human-readable and well structured nodes.

Once you've gotten very comfortable with JSX, you'll eventually need some sort of architectural pattern for any remotely complex app. You'll want to check out some Flux implementations. I personally use redux (which is not technically Flux) and highly recommend it. The Flux stuff has a decent learning curve, but once it all clicks it makes sense why that type of pattern works so well with React. There is a great video series by Redux's creator here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM