Common-Js and Material-UI Icons. Understanding why Icon won't load. (React Js) - reactjs

I'm attempting to run the following code:
"use strict";
var React = require('react');
var Router = require('react-router');
var Link = Router.Link;
var Material = require('material-ui');
var ThemeManager = new Material.Styles.ThemeManager();
var Colors = Material.Styles.Colors;
var dropdown = Material.Icons.NavigationArrowDropDown; //This icon cannot be found
var Home = React.createClass({
childContextTypes: {
muiTheme: React.PropTypes.object
},
getChildContext: function () {
return {
muiTheme: ThemeManager.getCurrentTheme()
};
},
componentWillMount: function () {
ThemeManager.setPalette({
accent1Color: Colors.cyan500
});
},
render: function () {
return (
<div>
<Material.AppBar title="Test" showMenuIconButton={false}>
</Material.AppBar>
<Material.List>
<Material.ListItem primaryText={"Queue"} leftIcon={<Material.Icons.NavigationChevronLeft/>} />
<Material.ListItem primaryText={"Log"} leftIcon={<Material.Icons.NavigationArrowDropDown/>} />
<Material.ListItem primaryText={"Settings"} />
</Material.List>
<Material.Paper>
<span>This is some text</span>
<Material.RaisedButton label="Super Secret Password" primary={true}/>
</Material.Paper>
</div>
);
}
});
module.exports = Home;
I've included the necessary packages and the code runs fine if I don't include
Material.Icons.NavigationArrowDropDown;
I've navigated to material-ui (0.11.1) and the file does exist there as an export in the following path:
lib > svg-icons > Navigation > Arrow_drop_down.js and the source code is as follows:
'use strict';
var React = require('react/addons');
var PureRenderMixin = React.addons.PureRenderMixin;
var SvgIcon = require('../../svg-icon');
var NavigationArrowDropDown = React.createClass({
displayName: 'NavigationArrowDropDown',
mixins: [PureRenderMixin],
render: function render() {
return React.createElement(
SvgIcon,
this.props,
React.createElement('path', { d: 'M7 10l5 5 5-5z' })
);
}
});
module.exports = NavigationArrowDropDown;
However, when compiling and running the application it cannot find the item and complains it does not exist, yet the other item
Material.Icons.NavigationChevronLeft
Gets found without issue. This file (with the exclusion of my router and app.js) are my entire project.
Since both files exist in the same folder, I cannot understand why the one reference is found and the other isn't?
The error occurs at runtime and jsLint doesnt pick it up. Additionally, when removing the listItem icon my page renders correctly. The problem appears to be tied directly to this component.
Additional Note: I have removed the var dropdown, it was there merely to demonstrate how the export is not being found from Material UI.
tl;dr : Material UI Icon class in the same folder as another Icon class is not being picked up. Why?

As you can see in src/index.js, NavigationArrowDropDown isn't being set on Material.Icons, while NavigationChevronLeft is. The component is used in other places, but is never publicly exposed through material-ui's main export.
However, you can still require it like you would any other file:
var NavigationArrowDropDown = require('material-ui/lib/svg-icons/navigation/arrow-drop-down');
Looking at the README, it looks like this is the recommended way to reach single components.

Related

How to use NPM installed react component in JSX?

I'm trying to use a 3rd party react component (react-slick) within my JSX and running into a problem. I'm attempting to use it very similarly to within this example by the app creator (example1.jsx snippet below).
Whenever I do this I get 2 warnings and an error:
Warning: This JSX uses a plain function. Only React components are valid in React's JSX transform.
Warning: Something is calling a React component directly. Use a factory or JSX instead. See: http://fb.me/react-legacyfactory
Uncaught TypeError: Cannot read property '__reactAutoBindMap' of null
I have also tried something similar as example2.jsx, which was a solution found in another Stack Overflow question. However, while no warnings, or errors were thrown, in this case the code did not render at all.
I have tried various methods of using React.createFactory (which shouldn't be used in JSX to begin with), and other finagling but with no results.
This is probably a stupid question but how the hell do I use NPM installed components in my JSX?
example1.jsx:
var React = require('react');
var Slider = require('react-slick');
var SingleItem = React.createClass({
render: function () {
var settings = {
dots: true,
}
return (
<div>
<h3> Image slider with one item at a time</h3>
<Slider dots={true}>
<div><img src="/img/autumn.jpg" alt=""/></div>
<div><img src="/img/sun.jpg" alt=""/></div>
</Slider>
</div>
);
}
});
var App = React.createClass({
render: function () {
return (
<div className='container'>
<SingleItem />
</div>
);
}
});
example2.jsx:
var App = React.createClass({
render: function () {
return (
<div className='container'>
{SingleItem}
</div>
);
}
});
It looks like you aren't actually referencing the slider component. You may find that your solution looks more like
var Slick = require('react-slick');
var Slider = Slick.Slider
Use the debugger to check what object you are actually being given by the require. It is also possible that you need to require a component by directly referencing one of the libraries file e.g.
var Slider = require('./slider.jsx');
Take a look at the lib or dist directory also, you can see the module.exports value for your require.
Use this to include Slick Slider component:
var Slider = React.createFactory(require('react-slick'));

CSSTransitionGroup __reactAutoBindMap error

I'm trying to get started with React and CSSTransitionGroup. If I add my <MyTransitionGroup ../> I get the warning "Something is calling a React component directly", and the error "Uncaught TypeError: Cannot read property '__reactAutoBindMap' of undefined"
If I remove <MyTransitionGroup ../> - all is fine again. I checked the compiled js and <MyTransitionGroup ../> is compiled to React.createElement(MyTransitionGroup... - so it doesn't seem that the jsx compiler is out of date..
'use strict';
var React = require('react');
var Addons = require('react-addons');
var MyTransitionGroup = Addons.CSSTransitionGroup;
var style = require('./Screen.scss');
var Screen = React.createClass({
render: function () {
var style = {
backgroundColor: this.props.data.bgcolor
};
return (
<MyTransitionGroup transitionName="example" transitionAppear={true}> **// remove this and it works**
<div style={style} className="Screen">
{this.props.data.stitle}
</div>
</MyTransitionGroup>
);
}
});
module.exports = Screen;

Why is TestUtils.Simulate.click in Jest not working when used directly on React Components?

Let's say I have 2 components. A parent that contains a child.
The child component is a button like so:
var React = require('react');
var ChildButton = React.createClass({
onSubmitAnswer: function(e) {
this.props.onClick(this);
},
render: function() {
return (
<div className={this.props.visibility}>
<button onClick={this.onSubmitAnswer}>Click Me</button>
</div>
)
}
});
module.exports = ChildButton;
It lives within it's parent, which looks like this:
var React = require('react'),
ChildButton = require('./face-submit-button');
var ParentComponent = React.createClass({
onButtonSubmit: function() {
//Something happens here
},
render: function() {
return (
<div>
//Some more components
<ChildButton text="Submit" onClick={this.onButtonSubmit} />
</div>
)
}
});
module.exports = ParentComponent;
So far so good. Everything works as expected in the UI. But I've encountered some issues in the Jest tests using TestUtils.Simulate.click().
My test for the ChildButton component is straightforward and behaves as I would expect.
jest.dontMock('./child-button');
describe('ChildButton', function() {
var React = require('react/addons'),
ChildButton = require('./child-button'),
TestUtils = React.addons.TestUtils;
describe('events', function() {
var button,
onClickStub;
beforeEach(function() {
onClickStub = jest.genMockFn();
button = TestUtils.renderIntoDocument(
<ChildButton onClick={onClickStub} />
);
});
it('should call onSubmitAnswer when the button is clicked', function() {
var buttonTag = TestUtils.findRenderedDOMComponentWithTag(button, 'button');
TestUtils.Simulate.click(buttonTag);
expect(onClickStub).toBeCalled();
});
});
});
My test for the parent component started out looking the same:
jest.dontMock('./parent-component');
describe('ParentComponent', function() {
var React = require('react/addons'),
ParentComponent = require('./parent-component'),
ChildButton = require('./child-button'),
TestUtils = React.addons.TestUtils;
describe('events', function() {
var parent,
onClickStub;
beforeEach(function() {
onClickStub = jest.genMockFn();
parent = TestUtils.renderIntoDocument(
<ParentComponent onClick={onClickStub} />
);
});
it('should call onButtonSubmit when a click is triggered', function() {
var childButton = TestUtils.findRenderedComponentWithType(parent, ChildButton);
TestUtils.Simulate.click(childButton);
expect(onClickStub).toBeCalled();
});
});
});
But this test fails. The only difference I can see between these two tests is that one uses an HTML tag directly and clicks on it, while the other triggers a click on a React component. Can I not use the click event on React components directly? Is my assumption correct?
And if so, is there a way to trigger a click on React components differently in the tests? I tried using SimulateNative but that had the same effect, the onClickStub doesn't get called on click.
There is currently an open bug for this issue: Let ReactTestUtils.Simulate.click work on non-dom components. So the answer is that due to bugs, you can only use Simulate.click on an actual DOM node. So you can workaround the bug by getting the DOM node until it is fixed.

When should I use getInitialState in a React component

I have a React component that toggles a className when the component is clicked
var Foo = React.createClass({
getInitialState: function() {
return {className: ''}
},
render: function(){
var className = 'bar ' + this.state.className
return React.createElement('div', {className: className, onClick: this.onClick})
},
onClick: function() {
this.setState({className: 'baz'})
}
});
It works fine, but when I am rendering the app server side, I get the following error
Warning: getInitialState was defined on a component, a plain JavaScript class.
This is only supported for classes created using React.createClass.
Did you mean to define a state property instead?
My build step is setup like so
var Foo = require('./Foo');
var factory = React.createFactory(Foo);
module.exports = React.renderToString(factory({}));
Why is what I am doing wrong, and how should it be done?
I am not sure if this helps, but while using fluxible, this is the syntax i used with JSX as part of require component
var app = new Fluxible({
component: React.createFactory(require('./Components/startup.react.jsx'))
});

Testing React Class is Of Type

I'm attempting to test a react class which renders out several other react classes. All working perfectly apart from i'm not totally sure about the best practise in terms of testing this.
Code:
Parent Class:
module.exports = function (deps) {
var MixLink = require('views/components/mixLink')(deps);
return React.createClass({
render: function() {
return (
<div class="packshotData mixesPage" data-view="mixlist">
{
this.props.mixes.map(function (mix) {
return <MixLink mix={mix} />;
})
}
</div>
);
}
});
};
Child Class:
module.exports = function (deps) {
var Link = require('views/components/link')(deps);
var mixLink = React.createClass({
render: function() {
return (
<div className="packshotData-item packshotData-item-overlay">
<Link className="packshotData-item-link" href={this.props.mix.href} data-control="mixplay">
<img className="packshotData-item-image packshotHeadphones" src={this.props.mix.thumbnailHref} />
<div className="packshotData-item-title-overlay">
<span className="packshotData-item-title-text">{this.props.mix.name}</span>
</div>
</Link>
</div>
);
}
});
return mixLink;
};
Test:
describe('mixLinkList Component', function () {
var MixLinkList = require('views/components/mixLinkList')({}),
MixLink = require('views/components/mixLink')({}),
TestUtils = React.addons.TestUtils;
it('is a function', function () {
expect(MixLinkList).to.be.a(Function);
});
it('is create a MixLink for every mix', function () {
var mixes = [
{
href: 'http://mixlink.com/One',
name: "thunderbirds",
thumbnailHref: 'someUri'
},
{
href: 'http://mixlink.com/Two',
name: "captain scarlet",
thumbnailHref: 'someOtherUri'
}
],
renderedMixLinkList,
renderedComponents;
renderedMixLinkList = TestUtils.renderIntoDocument(
<MixLinkList mixes={mixes} />
);
renderedComponents = TestUtils.findAllInRenderedTree(renderedMixLinkList, function (elem) {
return TestUtils.isCompositeComponentWithType(elem, MixLink);
});
expect(renderedComponents.length).to.be(2);
});
});
The test currently fails.
I can achieve my goals by grabbing the DOM node and checking the actual HTML which to me seems messy as the HTML produced by MixLink is the concern of MixLink Class not the MixLinkList class.
What i would like to do is simply interrogate the rendered component and check it has two children of type MixLink. Is that possible?
Thanks in advance!
For the most part your test seems fine. I think the reason it's failing is that MixLinkList is creating its own MixLink component distinct from the one in the test. You create one MixLink component on line 2 of the parent class, and a different one on line 3 of the test. So the rendered list does not contain elements of the test's MixLink, but rather elements of the list's own link component.
Your method of dependency injection is both the problem and the solution. Simply change the parent class to begin:
module.exports = function (deps) {
var MixLink = deps.MixLink;
And the test can then inject the MixLink component like this:
var MixLink = require('views/components/mixLink')({}),
MixLinkList = require('views/components/mixLinkList')({
MixLink: MixLink
}),
TestUtils = React.addons.TestUtils;
You might also consider using a more specific TestUtils methods such as scryRenderedComponentsWithType (docs), which makes the last part of your test read easier:
renderedComponents = TestUtils.scryRenderedComponentsWithType(
renderedMixLinkList,
MixLink
);

Resources