I'm very new to React and might've bit off too much.
In my app, I'm trying to make a document builder (sort of like building emails in mailchimp). When you click on an element's icon, the markup for that element will be added to the document page.
Conceptually, I'm not sure of the best way to do this in React. My questions include:
- How do you track which elements have been added to the document?
- Do I manage state at the app level?
- Eventually, I'll want the user to customize styles of each element added to the document, where should that code live?
- It seems like order of the data and functions matters (sometimes it breaks when this order changes). Is there a better way to organize this?
For now, any advice on the 'react' way to set this up would be appreciated.
My main JS:
// ---------------------------------------------------------
// Elements
// ---------------------------------------------------------
var TextBlock = React.createClass({
render: function() {
return (
<p>Lorem ipsum ... laborum.</p>
);
}
});
var ImageBlock = React.createClass({
render: function() {
return (
<img src="placehold.it/360x240" alt="Image" />
);
}
});
var HeadingBlock = React.createClass({
render: function() {
return (
<h3>Heading Here</h3>
);
}
});
var TableBlock = React.createClass({
render: function() {
return (
<table>
... Table Markup Here ...
</table>
);
}
});
var ColumnsBlock = React.createClass({
render: function() {
return (
<div class="row">
<div class="col-xs-4">Col 1</div>
<div class="col-xs-4">Col 2</div>
<div class="col-xs-4">Col 3</div>
</div>
);
}
});
var Divider = React.createClass({
render: function() {
return (
<hr />
);
}
});
var elementList = [
{
'name': 'Text',
'icon': 'align-left',
'html': <TextBlock />
},
{
'name': 'Image',
'icon': 'picture-o',
'html': <ImageBlock />
},
{
'name': 'Heading',
'icon': 'header',
'html': <HeadingBlock />
},
{
'name': 'Table',
'icon': 'table',
'html': <TableBlock />
},
{
'name': 'Column',
'icon': 'columns',
'html': <ColumnsBlock />
},
{
'name': 'Divider',
'icon': 'times',
'html': <Divider />
},
];
var Element = React.createClass({
handleClick: function(e){
e.preventDefault();
this.props.handleClick();
},
render: function() {
return (
<li className="element" onClick={this.handleClick}>
<i className={'fa fa-' + this.props.icon}></i>
<span className="element__name">{this.props.name}</span>
</li>
);
}
});
var Elements = React.createClass({
getInitialState: function () {
return {
elementList: elementList,
};
},
handleClick: function(index, element){
console.log(element.html);
},
render: function() {
return (
<ul className="list-unstyled">
{this.state.elementList.map(function(element, index) {
return (
<Element
key={index}
handleClick={this.handleClick.bind(this, index, element)}
name={element.name}
icon={element.icon}
/>
);
}.bind(this))}
</ul>
);
}
});
// ---------------------------------------------------------
// Tabs
// ---------------------------------------------------------
var Tab = React.createClass({
handleClick: function(e){
e.preventDefault();
this.props.handleClick();
},
render: function() {
return (
<a className={this.props.isCurrent ? 'btn btn-primary' : 'btn btn-default'} onClick={this.handleClick}>
{this.props.name}
</a>
);
}
});
var Tabs = React.createClass({
handleClick: function(tab){
this.props.changeTab(tab);
},
render: function(){
return (
<div className="text-center">
<nav className="btn-group">
{this.props.tabList.map(function(tab, index) {
return (
<Tab
key={index}
handleClick={this.handleClick.bind(this, index)}
name={tab.name}
isCurrent={(this.props.currentTab === index)}
/>
);
}.bind(this))}
</nav>
</div>
);
}
});
var Settings = React.createClass({
render: function() {
return (
<div>test settings</div>
);
}
});
var tabList = [
{
'name': 'Content',
'content': <Elements />
},
{
'name': 'Settings',
'content': <Settings />
}
];
var Document = React.createClass({
render: function() {
return (
<article className="document__frame">
<div className="document">test</div>
</article>
);
}
});
var App = React.createClass({
getInitialState: function () {
return {
tabList: tabList,
currentTab: 0
};
},
changeTab: function(index) {
this.setState({ currentTab: index });
},
render: function() {
return (
<div>
<Document />
<div className="control">
<Tabs
currentTab={this.state.currentTab}
tabList={this.state.tabList}
changeTab={this.changeTab}
/>
<div className="control__panel">
{this.state.tabList[this.state.currentTab].content}
</div>
</div>
</div>
);
}
});
ReactDOM.render(
<App />,
document.getElementById('content')
);