Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React components? #9

Closed
rauschma opened this issue Jan 10, 2016 · 6 comments
Closed

React components? #9

rauschma opened this issue Jan 10, 2016 · 6 comments

Comments

@rauschma
Copy link

How do you handle React components (=function calls)? You could either have a registry for component names or do this:

class EchoComponent {
    ···
}
let comp = jsx`<${EchoComponent} />`;
React.renderComponent(comp, document.body);
@jgoux
Copy link

jgoux commented Feb 19, 2016

I'm interested too. I'd love to use this library but I don't know how to handle custom components.

@ungoldman
Copy link
Member

Just write a function that accepts parameters and returns a vdom element.

var vdom = require('virtual-dom')
var hyperx = require('hyperx')(vdom.h)

var initState = {
  wow: 'interesting'
}

function App (state, dispatch) {
  return hx`
    <div class="app">
      ${Component(state, dispatch)}
    </div>
  `
}

function Component (state, dispatch) {
  var data = { wow: 'cool' }
  return hx`
    <div onclick=${() => dispatch('event', data)}>
      ${state.object.prop}
    </div>
  `
}

function dispatch (action, data) {
  if (action === 'event') update(data)
}

function update (data) {
  // ...
}

function render () { /* ... */ }

Incomplete but hopefully illustrates the idea.

Edit: sorry hit enter too early, updated the above to be more complete.

@bmathews
Copy link

I've found that you can use components with React.createElement:

const React = require('react')
const hyperx = require('hyperx')
const hx = hyperx(React.createElement)

const Slider = require('react-slider')

module.exports = React.createClass({
  render() {
    return hx`<div className='controls__toolbar__volume__slider'>
      ${React.createElement(Slider, { value: this.props.volume, withBars: true })}
    </div>
  }
})

Not sure if there's an easier way or not.

Edit: Improved example

bmathews referenced this issue in bmathews/roll-call Oct 17, 2016
@niksy
Copy link

niksy commented Dec 30, 2016

For anyone looking for a "workaround" for this, I’ve managed to create a proof of concept. Basically, it uses function which returns another function in which we check first letter of tag element. If it’s uppercase, we treat it as component and evaluate that string to variable declaration.

This obviously only works if method is in scope and eval has access to defined variable. Maybe it could be made to work regardless of scope? It seems like this could be properly processed with hyperxify - if first letter is uppercased, don’t stringify tag name and just return original value.

Edit: it seems like proposal on processing has already been implemented in fork of hyperxify; maybe this could be somehow merged to original project?

function r ( h ) {
	return function ( tagName, attrs, children ) {
		if ( tagName[0].toLowerCase() !== tagName[0] ) {
			tagName = eval(tagName);
		}
		return h(tagName, attrs, children);
	}
}

const React = require('react');
const ReactDOM = require('react-dom');
const hyperx = require('hyperx');
const hx = hyperx(r(React.createElement));
const Slider = require('react-slider');

module.exports = React.createClass({
	render() {
		return hx`
			<div className='controls__toolbar__volume__slider'>
				<Slider value="${this.props.volume} withBars="${true}" />
			</div>`
		;
	}
});

Or example of a more complex implementation:

function r ( h ) {
	return function ( tagName, attrs, children ) {
		if ( tagName[0].toLowerCase() !== tagName[0] ) {
			tagName = eval(tagName);
		}
		return h(tagName, attrs, children);
	}
}

const React = require('react');
const ReactDOM = require('react-dom');
const hyperx = require('hyperx');
const hx = hyperx(r(React.createElement));

const Wrap = React.createClass({
	render: function () {
		return hx`<b>${this.props.children}</b>`;
	}
});

const Input = ( props ) => {
	return hx`<input type="text" defaultValue="${props.value}" class="${props.value}" onChange=${props.onChange} />`;
};

const App = React.createClass({
	getInitialState: function () {
		return {
			text: ''
		};
	},
	render: function () {
		return hx`
			<div>
				<span class="bar">
					<Wrap>${['foo','bar'].map(( value, index ) => {
						return hx`<Input value=${value} key="${index}" onChange=${this.handleChange} />`;
					})}
					</Wrap>
				</span>
				<b>${this.state.text}</b>
			</div>
		`;
	},
	handleChange: function ( ev ) {
		this.setState({
			text: ev.target.value
		});
	}
});
  
ReactDOM.render(React.createElement(App), document.querySelector('body'));

@tbranyen
Copy link

@rauschma inspired by your comment: https://github.com/tbranyen/diffhtml/tree/master/packages/diffhtml-components#examples

@goto-bus-stop
Copy link
Member

as of this PR #68, published in 2.4.0, you can use <${CustomComponent} prop=x> child </${CustomComponent}>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants