The public parts of my notebook.
loading
state and an error
state.
const PlanetView = ({ name, climate, terrain }) => (
<div>
<h2>{name}</h2>
<div>Climate: {climate}</div>
<div>Terrain: {terrain}</div>
</div>
);
export default class Dagobah extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
renderLoading() {
return <div>Loading...</div>;
}
renderError() {
return <div>I'm sorry! Please try again.</div>;
}
renderPlanet() {
const { name, climate, terrain } = this.state.planet;
return (
<div>
<h2>{name}</h2>
<div>Climate: {climate}</div>
<div>Terrain: {terrain}</div>
</div>
);
}
render() {
if (this.state.loading) {
return this.renderLoading();
} else if (this.state.planet) {
return this.renderPlanet();
} else {
return this.renderError();
}
}
}
class PlanetView extends React.Component {
renderLoading() {
return <div>Loading...</div>;
}
renderError() {
return <div>I'm sorry! Please try again.</div>;
}
renderPlanet() {
const { name, climate, terrain } = this.props.planet;
return (
<div>
<h2>{name}</h2>
<div>Climate: {climate}</div>
<div>Terrain: {terrain}</div>
</div>
);
}
render() {
if (this.props.loading) {
return this.renderLoading();
} else if (this.props.planet) {
return this.renderPlanet();
} else {
return this.renderError();
}
}
}
class DagobahContainer extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
render() {
return <PlanetView {...this.state} />;
}
}
export default DagobahContainer;
const LoadingView = () => <div>Loading...</div>;
const ErrorView = () => <div>Please try again.</div>;
const PlanetView = ({ name, climate, terrain }) => (
<div>
<h2>{name}</h2>
<div>Climate: {climate}</div>
<div>Terrain: {terrain}</div>
</div>
);
const PlanetBranch = ({ loading, planet }) => {
if (loading) {
return <LoadingView />;
} else if (planet) {
return <PlanetView {...planet} />;
} else {
return <ErrorView />;
}
};
class DagobahContainer extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
render() {
return <PlanetBranch {...this.state} />;
}
}
export default DagobahContainer;
const withDagobah = PlanetViewComponent =>
class extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
render() {
return <PlanetViewComponent {...this.state} />;
}
};
export default withDagobah(PlanetBranch);
loading
, error
, planet
- the "shape") of model and view must match exactly. You sometimes find yourself writing a special component to transform from one to another.
children
construct (Google it).
cloneElement
that I found not very readable.
const hoc = withPlanet('tatooine')(PlanetView);
class Dagobah extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
render() {
return this.props.render(this.state);
}
}
export default () => (
<Dagobah
render={({ loading, error, planet }) => {
if (loading) {
return <LoadingView />;
} else if (planet) {
return <PlanetView {...planet} />;
} else {
return <ErrorView />;
}
}}
/>
);
with
function, passes in a render function directly to the model component. No particular advantage, besides succinctness.
import React from "react";
import PropTypes from "prop-types";
const contextTypes = {
dagobah: PropTypes.shape({
loading: PropTypes.bool,
error: PropTypes.object,
planet: PropTypes.shape({
name: PropTypes.string,
climate: PropTypes.string,
terrain: PropTypes.string
})
})
};
// provider
export class DagobahProvider extends React.Component {
state = { loading: true };
componentDidMount() {
fetch("https://swapi.co/api/planets/5")
.then(res => res.json())
.then(
planet => this.setState({ loading: false, planet }),
error => this.setState({ loading: false, error })
);
}
static childContextTypes = contextTypes;
getChildContext() {
return { dagobah: this.state };
}
render() {
return this.props.children;
}
}
// higher order component
const withDagobah = PlanetViewComponent =>
class extends React.Component {
static contextTypes = contextTypes;
render() {
const { props, context } = this;
return <PlanetViewComponent {...props} {...context.dagobah} />;
}
};
const DagobahPlanet = withDagobah(PlanetView);
#medianotes #notebook