function useTimeout(ms = 0) {
const [ready, setReady] = React.useState(false);
React.useEffect(function () {
const int = setTimeout(() => setReady(true), ms);
return () => clearTimeout(int);
}, [ms]);
return ready;
}
function Demo(props) {
const done = useTimeout(2000);
return (
<div>
{done ? "DONE" : "WAITING"}
</div>
);
}
Conditional
{god ? (
{/* some jsx */}
) : (
{/* other jsx */}
)}
this.setState(state => ({
products: [...state.products, {name: 'NEW product'}]
}));
Also known as containment
function Popin(props) {
return (
<div className="Popin">
<div className="Popin__left">
{props.left}
</div>
<div className="Popin__right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<Popin
left={
<Contacts />
}
right={
<Chat />
} />
);
}
With Higher-order components, you create a function that takes in a component as its argument. From that function, you return a new component that encapsulates all of the shared logic and renders the component that was passed in. From there, you can pass any data to the rendered component via props.
function withHover(Component) {
return class extends React.Component {
state = {hovering: false};
handleHover = (e) => {this.setState({hovering: true})}
handleOut = (e) => {this.setState({hovering: false})}
render() {
return (
<div onMouseOver={this.handleHover} onMouseOut={this.handleOut}>
<Component hovering={this.state.hovering} {...this.props} />
</div>
);
}
}
}
// Call with:
const HoverButton = withHover(Button);
function withAuth(Component) {
return function AuthHOC(props) {
const { user } = useAuth()
if (user === false) return "you need to be logged in"
return <Component {...props} />
}
}
NB: 🧠 convoluted technique... Prefer using hooks
see: https://reactjs.org/docs/hooks-reference.html#usestate
const [clicks, setClicks] = useState(0); // preserve values between renders
const [clicks, setClicks] = useState(() => fibonacci(500)); // expensive initialization through a function
setClicks(clicks => click+1) // cannot just setClicks(clicks+1)
see: https://reactjs.org/docs/hooks-reference.html#useeffect
useEffect(() => {
// executed after any render (after render is painted to the screen)
})
useEffect(() => {
// executed after initial-render + after any render when `loggedin` changes
}, [loggedin])
useEffect(() => {
// executed after initial-render + after any render when `loggedin` OR `props.message` change
}, [loggedin, props.message])
useEffect(() => {
// executed after the initial-render
}, [])
useEffect(() => {
//
return () => {
// executed before any rerender (rerender = any but not the first one)
}
})
const [loggedin, setLoggedin] = useState(false);
useEffect(() => {
//
return () => {
// executed before any rerender but only if `loggedin` has changed
}
}, [loggedin])
function Timer() {
const intRef = useRef();
useEffect(() => {
const id = setInterval(() => {
// ...
});
intRef.current = id;
return () => {
clearInterval(intRef.current);
};
});
// ...
}
import React from "react";
const ThemeContext = React.createContext();
const themes = ["dark", "light"];
const initialState = {
name: "dark"
};
function reducer(state, action) {
switch (action.type) {
case "change":
if (themes.indexOf(value) !== -1) {
throw new Error("This theme `${action.value}` does not exist");
}
return {
..state,
name: value
};
case "reset":
return {
...initialState
};
default:
throw new Error(`This action: ${action.type} is not supported`);
}
}
// A new component that wraps children and allow them to consume the same reducer (complex state)
export default props => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const value = [state, dispatch]; // `value` is what useTheme() function will return/expose
return (
<ThemeContext.Provider value={value}>
{props.children}
</ThemeContext.Provider>
);
};
// Defining a `useTheme` hook that will consume the provided context
function useTheme() {
return React.useContext(ThemeContext); // will return `value` to any component that `useTheme()`
}
export { useTheme };
- cf. My implementation of the above useTheme hook : https://codesandbox.io/s/jolly-ganguly-x0icz
- cf. Same implementation, but simpler, without useReducer : https://codesandbox.io/s/laughing-bohr-b63eo
- cf. https://medium.com/simply/state-management-with-react-hooks-and-context-api-at-10-lines-of-code-baf6be8302c
see: https://codesandbox.io/s/trusting-dijkstra-bj5le
Instantiate a Auth
provider once,
Then apply withAuth
to any component you want to have access to props.auth