Skip to content

Instantly share code, notes, and snippets.

@busypeoples
Created May 8, 2016 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save busypeoples/8b44732ba9b9fcbcf32aac12def32b2b to your computer and use it in GitHub Desktop.
Save busypeoples/8b44732ba9b9fcbcf32aac12def32b2b to your computer and use it in GitHub Desktop.
Devcards for React - initial ideas
import React, { PropTypes, Component } from 'react';
import { createStore, combineReducers } from 'redux';
import { render } from 'react-dom';
import foobar from './SomeComponent';
import StateBar from './SomeStatefulComponent';
const devCardStyle = {
background: '#eee',
padding: '20px',
marginBottom: '10px'
};
// state handling....
const initialState = [];
const cards = (state = initialState, action) => {
switch (action.type) {
case 'ADD':
return [...state, action.payload];
case 'UPDATE':
return state;
default: return state;
}
};
const rootReducer = combineReducers({ cards });
const store = createStore(rootReducer, ({ cards: []}));
function devCard(Component, state, headline) {
store.dispatch( { type: 'ADD', payload: {type: 'card', Component, state, headline}} );
}
// not implemented...
function devMarkDown(text, headline) {
store.dispatch( { type: 'ADD', payload: {type: 'text', state: text, headline} } );
}
class App extends Component {
render() {
return <Render {...this.props} />
}
}
class Render extends Component {
constructor(props) {
super(props);
const { cards } = this.props;
this.state = { cards };
}
shouldComponentUpdate(nextProps, nextState) {
// for testing purposes...
return true;
}
componentWillReceiveProps(nextProps) {
}
render() {
const { cards } = this.props;
return (
<div>
{cards.map((c, index) => {
const { type, Component, state, headline } = c;
if (type === 'card') {
return <div key={index}>
<h5>Dev Card {headline? headline : null}</h5>
<div style={devCardStyle}>
<Component {...state} />
</div>
</div>
} else {
return <div key={index}>
<div style={devCardStyle}>
<div>{ state }</div>
</div>
</div>
}
})}
</div>
);
}
}
store.subscribe(() => {
render(<App {...store.getState()} />, window.app);
});
devCard(StateBar, {left: 150}, 'test a stateful component!');
devCard(foobar, { name: 'foobar!', model: 30 }, 'some state...');
devMarkDown(`
#A Headline
##A subtitle.
Some text...
`);
{
"name": "dev-cards-example",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --hot",
"start": "webpack --progress --colors --watch",
"build": "webpack --config webpack.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"react": "^0.14.8",
"react-dom": "^0.14.8",
"redux": "^3.5.2"
},
"devDependencies": {
"babel-core": "^6.7.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"react-hot-loader": "^1.3.0",
"webpack": "^1.12.14",
"webpack-dev-server": "^1.14.1"
},
"babel": {
"presets": [
"es2015",
"react"
]
}
}
import React, { PropTypes } from 'react';
const foobar = (props) => (
<div>
<h3>Testdrive. Stateless. Yes.</h3>
<div>{props.name}</div>
<div>{props.model}</div>
</div>
);
foobar.propTypes = {
name: PropTypes.string.isRequired,
model: PropTypes.number.isRequired,
};
export default foobar;
import React, { Component } from 'react';
export default class SomeStatefulComponent extends Component {
constructor(props) {
super(props);
this.state = {ticked: 0, left: 0};
this.tick = null;
}
componentDidMount() {
this.transition(this.props);
}
componentWillReceiveProps(nextProps) {
//this.transition(nextProps);
}
transition(nextProps) {
// some random and quick transition example...
this.tick = setInterval(function() {
let ticked = this.state.ticked + 1;
let left = this.state.left;
if (left < nextProps.left) {
left += 1;
} else if (nextProps.left < left) {
left -= 1;
} else {
clearInterval(this.tick);
}
this.setState({ticked: ticked, left: left });
}.bind(this), Math.abs(nextProps.left - this.state.left)/1000);
}
componentWillUnmount() {
clearInterval(this.tick);
}
render() {
const left = this.state.left;
return <div>
<div style={{ paddingLeft: `${left}px` }}>Some Other Box</div>
</div>
}
}
'use strict';
const path = require('path');
const Webpack = require('webpack');
const ASSETS_PATH = path.resolve(__dirname, 'build');
const NAME = 'index.js';
const PORT = 8080;
const SERVER_URL = 'http://localhost:' + PORT;
module.exports = {
debug: true,
devtool: 'eval-source-map',
entry: [
'./' + NAME
],
output: {
path: ASSETS_PATH,
publicPath: 'build',
filename: NAME,
},
module: {
loaders: [
{ test: /\.js$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
{ test: /\.css$/, loader: 'css?minimize' },
{ test: /\.less$/, loader: 'css?sourceMap&localIdentName=[name]__[local]!postcss!less?sourceMap' },
{ test: /\.(woff|woff2|ttf|eot|svg)(\?]?.*)?$/, loader: 'url-loader?limit=8192' },
{ test: /\.(gif|jpg|jpeg|png)(\?]?.*)?$/, loader: 'url-loader?limit=1024' },
{ test: /\.json$/, loader: 'json', exclude: /node_modules/ },
],
},
plugins: [
new Webpack.NoErrorsPlugin()
],
devServer: {
port: 8080,
contentBase: "./",
hot: true,
quiet: false,
noInfo: false,
inline: true,
colors: true,
historyApiFallback: true
},
babel: {
presets: ['react', 'es2015']
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment