My humble beginnings with React.js
I was curious to find out what my first production usage of React to end users so I checked out the history of one particular project that I developed on and found out that my first React version was v0.4.1 ๐
The first React version was v0.3.0 was released on 2013-07-02 and v0.4.1 was released at the end of July, this definitely means that I was among the first early adopters of React ๐
Unfortunately, I only stored the final compiled build artifacts, I started using version control 2 years later (hey, better late than never ๐), so I don't have an exact source tree of what the code was.
Luckily the code is unminified/uncompressed1, so Iโm able to piece together how I done front-end development 5 years ago and surprised myself along the way:
- Third-party vendor files are just copied to the workspace
No usage of npm2 yet, and no easy way to track new versions by the authors - All the JavaScript for the background/content/popup pages are written in separate big combined files
Back then, concatenating multiple small files and combining into one big file was the usual practice, hope you donโt mess up the load order... - I didnโt use JavaScript modules such as CommonJS or AMD, no Browserify/webpack usage yet
- No usage of Babel, not even sure if 6to5 was created yet. Lots of classical JavaScript and
var
usage - No CSS preprocessor, no usage of Less/SASS
- As this project is a Chrome extension for Chrome 20+ (wow, that felt like brand new many years ago...), I didnโt use jQuery and just directly access the browser DOM with vanilla JS
- However, I did use Zepto to easily animate fade effects
- Remember that React is originally developed and used at Facebook for small chunks on their regular server-rendered PHP/Hack pages, thatโs how I originally used and bolted on React to this project too.
Somehow some people think that React is for Single Page App (SPA) or you have to rewrite your entire app to use React, thatโs definitely not the case - Only 2 React components were created on my first version. I was still experimenting and evaluating React at that time, okay? ๐
- JSX was still relatively new, you have to use some JSXTransformer thingy. I chose not to use it, and used regular function calls instead
- Using
React.createClass
instead of ES6 classes - Using
React.DOM.*
factories to generate elements, itโs deprecated nowadays - Doing silly things such as mutating
this.props
- No type safety system is used, no usage of Flow/TypeScript, the best is a comment at the top telling which props that would be accepted
- Comma-first code style ๐คช
- IIRC no build tools are used yet, no Grunt or Gulp
- Code quality wasnโt a priority/considered, no usage of JSLint/JSHint/JSCS/ESLint yet
Here is the code to give you a closer understanding of the past:
// React components
// props: text, rawText, className, noFlashYellow
var RadioTrackInfoText = React.createClass({
getInitialState: function() {
if (!this.props.rawText) {
this.props.rawText = this.props.text;
}
}
,componentDidMount: function(rootNode) {
if (this.props.rawText) {
this.wordwrap(rootNode);
}
}
,shouldComponentUpdate: function(nextProps, nextState) {
if (!this.props.rawText) {
this.props.rawText = this.props.text;
}
if (!nextProps.rawText) {
nextProps.rawText = nextProps.text;
}
// If the text are the same, tell React to not update
if (nextProps.rawText === this.props.rawText) {
return false;
}
return true;
}
,componentDidUpdate: function(prevProps, prevState, rootNode) {
if (this.props.rawText) {
if (!this.props.noFlashYellow) {
flashYellow(rootNode);
}
this.wordwrap(rootNode);
}
}
,wordwrap: function(node) {
if (needsEllipsis(this.props.rawText)) {
addClass(node, 'hasEllipsis');
node.title = this.props.rawText;
} else {
removeClass(node, 'hasEllipsis');
node.title = '';
}
}
,render: function() {
return React.DOM.p({className: this.props.className}, this.props.text);
}
});
// props: track, artist, event, event.title, is_live, text, noFlashYellow
var RadioTrackInfo = React.createClass({
render: function() {
if (this.props.text === STREAMOFFLINETEXT) {
this.props.track = "Offline";
this.props.artist = '';
}
var children = [];
// Event info
if (this.props.event || this.props.is_live) {
var eventTitle = '';
if (this.props.is_live) {
eventTitle = "Live";
if (this.props.event && this.props.event.title) {
eventTitle = "Live: " + this.props.event.title;
}
} else {
eventTitle = "On Air";
if (this.props.event && this.props.event.title) {
eventTitle = "On Air: " + this.props.event.title;
}
}
children.push(RadioTrackInfoText({
text: [
React.DOM.i({className:'icon-star'})
,eventTitle
]
,rawText: eventTitle
,className: 'eventInfo'
,noFlashYellow: this.props.noFlashYellow
}));
}
if (extStatus.settings.compact) {
var text = this.props.track;
if (text) {
text += ' - ';
}
text += this.props.artist;
if (this.props.text === STREAMOFFLINETEXT) {
text = "Offline";
}
children.push(RadioTrackInfoText({text: text, noFlashYellow: this.props.noFlashYellow}));
} else {
children.push(RadioTrackInfoText({text: this.props.track, noFlashYellow: this.props.noFlashYellow}));
children.push(RadioTrackInfoText({text: this.props.artist, noFlashYellow: this.props.noFlashYellow}));
}
return React.DOM.div(null, children);
}
});
Even I felt like facepalming at some of the code/decisions there, oh well, learn from your past mistakes and see how your skills have improved over the years ๐
1 This is a Chrome extension project and I felt itโs less important to minify files on downloadable software
2 I never used Bower