key
changes, React will create a new component (note: it does not actually re-render or update).this.forceUpdate();
For just a single attribute, the easiest is to set it to null
to prevent it from rendering. For some attributes, React is smart enough that you can use false
instead of null
.
<button disabled={isDisabled ? true : null}>Launch Missle</button>
When you have several attributes, this is a nice way to do it. Build an object how you like:
var inputProps = { value: 'foo', onChange: this.handleChange }; if (condition) inputProps.disabled = true;
Render with spread, optionally passing other props also. Notice how the order below makes a difference.
<input value="this is overridden by inputProps" {...inputProps} onChange={overridesInputProps} />
import React from 'react' import PropTypes from 'prop-types'; let UserName = (props) => ( <div> <p>{fullName}</p> </div> ) UserName.propTypes = { fullName: PropTypes.string, date: PropTypes.number.isRequired } // You can specify default values for optional properties. UserName.defaultProps = { fullName: 'George Washington' } export default UserName
React properties are allows passed into a component as a an object. In the above
example you can see fullName is destructured from the props on line 3. Because fullName
is inside curly braces, we know that it is getting destructured.
import React from 'react'; import PropTypes from 'prop-types'; class Greeting extends React.Component { constructor (props) { super(); this.curTime = new Date().toLocaleTimeString(); } render () { return <p>Hello, {this.props.userName}. Today, at {this.curTime}, it is {this.props.weather}.</>>; } } Greeting.propTypes = { userName: PropTypes.string, weather: PropTypes.string.isRequired }; // You can specify defaults for the optional props. Greeting.defaultProps = { userName: 'Earthling' }; export default Greeting;
JSX Attributes to get rendered to the DOM if they are a valid attribute. You can force non-standard attributes to render by putting a dash in the name; best practice is to use data-...
export default (...props) => ( <input type='checkbox' monsterFood='granola' data-uniqueId='Dracula' /> )
will render to the DOM as:
<input type="checkbox" data-uniqueId="Dracula">
The React component will still have a property called monsterFood
.
JSX does not support if statements, but you can use Javascript's ternary and boolean operators.
<p>{style === 'IPA' ? 'Is bitter' : 'Is not bitter'}</p>
<p>{style === 'IPA' && 'Is bitter'}</p>
let studentIsAgeOfMajority = false; <p>{!(studentIsAgeOfMajority) && 'Parent’s permission needed'}</p>
Is equivalent to:
let studentAge = 16; <p>{(studentAge < 18) && 'Parent’s permission needed'}</p>
To pass parameters to an event, see this post.
Basically, the component the captures the event must have a private function to handle the event. You attach the private function to the, say, onClick event. The private function then calls the function passed down via props.
Refs are kinda like specifying an ID on an element. You can then reach into the DOM (via ReactDOM.findDOMNode()) by the ref name. Example:
class RandomSpinner extends React.Component { constructor(props) { super(props); this.refCompass = React.createRef(); } onSpin = () => { this.refCompass.current.blur(); // Use `current` to get the actual DOM element. } render () { return ( <div ref={this.refCompass}>This is the compass elem.</> ) } }
This is a great place to hook-up event listeners. e.g.
componentDidMount() { ReactDOM.findDOMNode(this).addEventListener('click', this.onClick); }
setState()
here.setState()
.setState()
here.For one-off, quick-n-dirty solution you can use .bind()
to pass one, or more, values.
this.clickHandler.bind(this, val1, val2, val3)
render: function() { let items = this.props.items; return ( <ul> {() => { items.map((item) => { // bind the components onItemClick method // and use the bind syntax that prepends // arguments to attach the item argument let boundItemClick = this.onItemClick.bind(this, item); // Construct the onClick with our bound function return <li key={item.id} onClick={boundItemClick}>{item.title}</li> }); }()}; </ul> ); }, onItemClick: function(item, e) { console.log(item); }
This could be all done in one line:
return <li onClick={this.onItemClick.bind(this, item)}> ... </li>
The same thing can be done less verbosely with fat arrow functions.
return <li onClick={() => this.onItemClick(item)}> ... </li>
If you must write native ES5 code, this style can be used.
function HelloWorld () { return ( <div>Hello {this.props.name}</div> ) }
var React = require('react') var ReactDOM = require('react-dom') var HelloWorld = React.createClass({ // The createClass function actually creates a Component. render: function(){ return ( <div> Hello World! </div> ) } }); ReactDOM.render(<HelloWorld />, document.getElementById('app'));
The biggest gotcha is pulling out the error text into a location where you can use it.
import React from "react"; export default class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // Update state so the next render will show the fallback UI. return { hasError: true, error: error.name + " " + error.message }; } componentDidCatch(error, info) { // Use this to log errors. this.error = error.name + " " + error.message; } render() { if (this.state.hasError) { return ( <React.Fragment> <h1> Something went wrong.{" "} <span role="img" aria-label="Sad face" style={{ fontSize: "2em" }}> 😞 </span> </h1> <p>Error: {this.state.error}</p> </React.Fragment> ); } return this.props.children; } }