How to use NPM installed react component in JSX? - reactjs

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'));

Related

Default values of props in ReactJS

How can I define default values in ReactJS?
var Header = React.createClass({
render: function() {
return (
<h1>{this.props.title} if not defined insert "Title"</h1>
)
}
});
I extremely increased my React skill and as of 2018 this example (I
wrote at the question body) is outdated. You should do it like
#VladyVeselinov shown at the picture using ES6 classes and babel
transforms like babel-class-properties that allow you to make static
fields for your components
Since your example uses the createClass version of creating a component, you can use the getDefaultProps function.
https://facebook.github.io/react/docs/react-without-es6.html#declaring-prop-types-and-default-props
getDefaultProps: function() {
return {
title: 'Title'
};
}

how to access methods of an instance of a React component?

Is there a way to call the methods that a React component defines internally?
I understand generally we want to be passing values around declaratively with props/data etc. However I am using some component libraries that have internal useful methods.
eg
var field = <AutoComplete/>;
field.setValue("ready"); // doesn't work
eg this method
https://github.com/callemall/material-ui/blob/master/src/auto-complete.jsx#L244-L248
in material-ui AutoComplete component.
You can not do this with virtual dom, since virtual dom is just a description of components to be created(actual component instance will be created or updated only when rendering).
But you can access component instances inside your react component after rendering using refs:
var Test = React.createClass({
getInitialState: function(){
return {value:0};
},
setValue: function(value){
this.setState({value:value});
},
render: function() {
return <div>Value {this.state.value}</div>;
}
});
var App = React.createClass({
render: function() {
return <div>
<Test ref="test"/>
<button onClick={()=>this.refs.test.setValue(1)}>1</button>
<button onClick={()=>this.refs.test.setValue(2)}>2</button>
<button onClick={()=>this.refs.test.setValue(3)}>3</button>
</div>;
}
});
var mountNode = document.getElementById('app');
ReactDOM.render(<App name="John" />, mountNode);
jsbin with code above: http://jsbin.com/kitehujaje/1/edit?js,output

How to render array of objects in reactjs 1.0 with jsx?

I have the following:
var repos = [{"keya":"vala","keyb":"valb"},{"keya":"vala","keyb":"valb"},{"keya":"vala","keyb":"valb"}]
In my react component code:
var React = require('react');
var Repos = React.createClass({
propTypes: {
username: React.PropTypes.string.isRequired,
repos: React.PropTypes.array.isRequired
},
render: function() {
return (
<div> REPOS<br />
Username: {this.props.username} <br />
Repos: {this.props.repos}
</div>
)
}
});
module.exports = Repos;
I see that:
{this.props.repos} returns the above, but I am getting an error:
Uncaught Error: Invariant Violation: Objects are not valid as a React child... check the render method.
How do I get around this? Is there a way to just output everything without iterating/looping through each one? I know I can do so in AngularJS, but I don't get why react is giving me a hard time.
I am using the newest version of react; I don't think this was a problem with 0.13.
Stringify it:
{JSON.stringify(this.props.repos)}
That depends on how you want to display the values in your HTML.
You could do something like
render: function() {
return (
<div> REPOS<br />
Username: {this.props.username} <br />
Repos:
{this.props.repos.map(function(repo){
return <div><span>{repo.keya}</span></div>;
}}
</div>
)
}
In general, you want to iterate over the array of values and return a HTML representation of it. That is why you are getting the error you mentioned, React doesn't provide a default HTML representation of an object so there is no way it will know how to display your array.
If you just want to display it as a text then the stringify method on the other answer is the way to go. But if you are expecting a pretty formatted output you will have to iterate over the array.

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

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.

React update state if image not found.

I can't seem to wrap my head around this problem. What I'm trying to do is have React attempt to verify an image is not returning a 404 to display an alternative image instead. Something like the below does not work as React does not wait for the image to attempt to load for returning the component.
getInitialState: function () {
var img = new Image();
img.onerror = function() {
img.src = "alternativeImage.jpg"
},
img.src = this.props.image;
return {image: <img src={img.src} />};
},
The above code will display the images just fine but the 404 alternative image does not show up.
I've tried to place this in another method outside of getInitialState. I've also tried to have it call an external method outside of the React component, but nothing works.
There is a short hand method of adding onerror attribute on the image tag itself, but it seems React has the same issue of not executing that code and or updating itself based on the outcome.
I think the most frustrating part is that I cannot seem to have any function called that React would be able to work with from the JavaScript image object.
Thanks for any help you can provide.
Here's a solution that I came up with. Pretty new to React and programming in general so take this with a grain of salt....
const DEFAULT_IMAGE="http://i.imgur.com/lL3LtFD.jpg"
<img src={this.props.SRC} onError={(e)=>{e.target.src=DEFAULT_IMG}}/>
WARNING: If the default constant is invalid, the browser will be caught in an infinite loop (at least when I tested this in Chrome).
I haven't found a solution to this yet, but in vanilla javascript, you set the onerror attribute to null which tells the browser to make only a single request for the asset.
jQuery/JavaScript to replace broken images
It's a bad habit to put components into state. What you probably want is something like the following:
var Img = React.createClass({
componentDidMount: function () {
var self = this;
var img = new Image();
img.onerror = function () {
self.setState({ src: 'http://i.imgur.com/lL3LtFD.jpg' });
};
img.src = this.state.src;
},
getInitialState: function () {
return { src: '/404.jpg' };
},
render: function () {
return <img src={this.state.src} />;
}
});
jsfiddle link: http://jsfiddle.net/e2e00wgu

Resources