-
Notifications
You must be signed in to change notification settings - Fork 4
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
Any ideas about some other helpers that could be included in this repo? #5
Comments
I was thinking about a decorator that would transform a stateless function component into a component class. It could be useful when you want to apply a decorator that needs a class as input. For example: @someDecorator
class Person extends Component {
@injectProps
render({ firstName, lastName, email }) {
return <p>{ firstName } { lastName } - { email }</p>;
}
} ...would look like this: @someDecorator
@makeStateful
const Person = ({ firstName, lastName, email }) => (
<p>{ firstName } { lastName } - { email }</p>
); I'm not sure about the name, but I thought |
@jguyon the thing is decorators only work with classes, and "const Person = () => (...);" is just a function. But you could make a javascript function to help you with that: function makeStateful(renderFunction) {
return class StatefulComponent extends React.Component {
render() { return renderFunction(this.props); }
};
}
export default makeStateful; import makeStateful from './makeStateful';
const Person = makeStateful(({ firstName, lastName, email }) => (
<p>{ firstName } { lastName } - { email }</p>
));
export default Person; If you don't mind me asking, why do you feel the need to have a stateless component with state? Thanks |
@goncalvesjoao I'm sorry, I badly articulated my thoughts and I chose a very bad name for the helper. I chose Because stateless function components don't have a backing instance, it means you can't access their node via |
Sorry for the late replay @jguyon. In on of my apps I have a small CloseButton Component: import { killEvent } from 'relpers';
const CloseButton = ({ id, closeTab, stickable }) => (
stickable
? <noscript />
: <span
className="glyphicon glyphicon-remove"
onClick={ killEvent(() => closeTab(id)) }
/>
);
export default CloseButton; Its spec is really simple too, but needs this helper function first: import TestUtils from 'react-addons-test-utils';
import { findDOMNode } from 'react-dom';
function renderStateless(Component, props) {
const wrapper = TestUtils.renderIntoDocument(<div><Component { ...props } /></div>);
return findDOMNode(wrapper).children[0];
}
export default renderStateless; CloseButtonSpec.js: import chai from 'chai';
import React from 'react';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import TestUtils from 'react-addons-test-utils';
import renderStateless from '../support/renderStateless';
chai.use(sinonChai);
import CloseButton from '../../../src/nav-tabs/components/CloseButton';
describe('CloseButton', () => {
context('when stickable prop is true', () => {
it('<noscript /> should be returned', () => {
const closeButton = renderStateless(CloseButton, { stickable: true });
// see: https://developer.mozilla.org/en-US/docs/Web/API/Node
expect(closeButton.nodeName).to.be.equal('NOSCRIPT');
});
});
context('when stickable props is not used or false', () => {
it('closeTab prop callback should be called with id prop in it', () => {
const closeTabStub = sinon.spy();
const closeButton = renderStateless(CloseButton, { id: 1, closeTab: closeTabStub });
// see: https://facebook.github.io/react/docs/test-utils.html
TestUtils.Simulate.click(closeButton);
// see: http://chaijs.com/plugins/sinon-chai
expect(closeTabStub).to.be.calledWith(1)
});
});
}); |
The example above solves our need but checkout this tool: https://github.com/jquense/teaspoon I ended up remaking the CloseButtonSpec with teaspoon and it looks like this: import chai from 'chai';
import $ from 'teaspoon';
import React from 'react';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
chai.use(sinonChai);
import CloseButton from '../../../src/nav-tabs/components/CloseButton';
describe('CloseButton', () => {
context('when stickable prop is true', () => {
it('<noscript /> should be returned', () => {
const $closeButton = $(<CloseButton stickable={ true } />).render();
// see: https://developer.mozilla.org/en-US/docs/Web/API/Node
expect($closeButton.dom().nodeName).to.be.equal('NOSCRIPT');
});
});
context('when stickable props is not used or false', () => {
it('closeTab prop callback should be called with id prop in it', () => {
const closeTabStub = sinon.spy();
const $closeButton = $(<CloseButton id={ 1 } closeTab={ closeTabStub } />).render();
// see: https://github.com/jquense/teaspoon
$closeButton.trigger('click');
// see: http://chaijs.com/plugins/sinon-chai
expect(closeTabStub).to.be.calledWith(1)
});
});
}); cool tool uh? |
How about a decorator to apply mixins to give retrocompatibility with mixins like the one in yahoo/react-intl 1.x. Something like this: function applyMixin(mixin) {
return target => {
const mixed = Object.assign({}, mixin, target.prototype);
target.prototype = mixed;
return target;
};
} Then you can just do: import React from 'react';
// import mixin
import {
IntlMixin,
} from 'react-intl';
// import decorator
import {
applyMixin,
} from 'relpers';
// apply mixin to ES6 class
@applyMixin(IntlMixin)
class MyComponent extends React.Component {
render() {
return (
<div>
{ this.getIntlMessage('message') }
</div>
);
}
}
export default MyComponent; I don't know if that is the best way to code that decorator, but it works and if your component has a method with the same name then the component method overwrite the mixin method. Also, I don't tested if this works with things like Example working (without React, but the idea is the same): http://codepen.io/sergiodxa/pen/YwNjdJ? |
that's actually a great ideia @sergiodxa |
Check it out @sergiodxa I've made a branch for you: https://github.com/goncalvesjoao/relpers/tree/applyMixin It contains Specs and documentation for your ideia, but it doesn't include the code for the decorator. You just need to fork this repo, checkout the applyMixin branch, run npm install, then npm test to see the specs failing and fill in the blanks of src/applyMixin.js untill all tests are green. When all specs are green you should be able to see the example at: http://localhost:9000/api_docs/apply_mixin work If you have any doubts or don't feel like it, let me know. |
I just create the Pull Request with the decorator ready. |
Thanks for such a thorough PR man ✋ |
@sergiodxa sorry, I accepted your PR but forgot to publish it to npm. |
I have another idea, but I think is complicated, I think it will be really helpful a decorator the can detect if the user is logged and render a component, something like I think the best way is that the decorator need to be a React.Component that check the contextType to validate if |
No description provided.
The text was updated successfully, but these errors were encountered: