Create components in JavaScript using React. Conceptually, rendering logic and other UI logic are closely coupled; separate concerns by components instead of by HTML/JS/CSS. Composition > inheritance. And top-down data flow (but children can change other children/parent's state by calling shared parent's functions that are passed down to them via immutable props).
Just one of the things I'm learning. https://github.com/hchiam/learning and https://github.com/hchiam/learning-frameworks
Update: You can create a React web app by running one command: npx create-react-app my-app
(Update update: maybe use nx instead). Or you can use Yeoman generators like this or this or try out a RealWorld spec app. Or use Next.js.
2020 React cheatsheet (with code examples)
click to expand/collapse
https://codepen.io/gaearon/pen/ZpvBNJ
Shortest React example:
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') );
https://stackoverflow.com/questions/34737898/a-simple-hello-world-in-react-js-not-working
https://codepen.io/hchiam/pen/jmxVzV
LearnCode.academy tutorial on YouTube
https://tutorialzine.com/2014/07/5-practical-examples-for-learning-facebooks-react-framework/
and
https://facebook.github.io/react/docs/hello-world.html
Facebook provides a direct link to its React JS file (and its React object and its methods) that you can embed in your HTML file:
<script src="https://fb.me/react-0.10.0.min.js"></script>
Then you can call React.createClass()
with an object of options and methods.
It's recommended (but not required) to use the JSX dialect of JS (JavaScript) to write React web apps.
If you do use JSX, then: JSX --(compile)--> JS (for browser to interpret)
FCC: https://github.com/hchiam/chat-app-fcc-react-redux
https://codepen.io/hchiam/pen/LymLzP (vs a pure html version: https://codepen.io/hchiam/pen/jmxVzV)
https://codepen.io/hchiam/pen/ybjXPE?editors=1010
https://codepen.io/hchiam/pen/YVLrBb
https://codepen.io/hchiam/pen/rmvGgd
https://codepen.io/search/pens/?q=react&limit=hchiam&show_forks=true
click to expand/collapse
(To try my examples, npm install && npm run build
and then open all the html files with open *.html
.)
https://reactjs.org/docs/hello-world.html
https://reactjs.org/tutorial/tutorial.html -> https://codepen.io/hchiam/pen/BayOeZo?editors=0010
https://www.freecodecamp.org/learn/front-end-libraries/react
Firefox: https://addons.mozilla.org/en-US/firefox/addon/react-devtools -> open dev tools -> Components tab
Chrome: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
ng-if
? -> JavaScript if
/ternary or embedded shorthand {isTrue && <p>show this</p>}
or return null
ng-for
? -> JavaScript loop or map
(for example: numbers.map((n) => <li>{n}</li>);
)
You can even do this:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
ReactDOM.render(
<ul>{listItems}</ul>, // <ul> an array of <li>#</li>'s
document.getElementById("root")
);
https://reactjs.org/docs/thinking-in-react.html
-
Good to re-read the above link for details.
-
But general overview:
- mock/boxes
- hierarchy/"tabs"
- static version (NO interactivity, so think about state/props later)
- minimal state representation = {not passed-in prop, changes, not computable} -> (compute the rest)
- where state should live ("shared" state? may need to be in parent -> pass down state and callback as props to children)
- add inverse data flow, i.e. pass down state and callbacks as props to children, as identified in previous steps.
<!-- parameters will be extraParameter and e (implicit with bind) -->
<button onClick={(e) => this.handleClick(extraParameter, e)}>Do something</button>
<button onClick={this.handleClick.bind(this, extraParameter)}>Do something</button>
Special prop props.children
lets you do this:
function FancyBorder(props) {
return (
<div className={"FancyBorder FancyBorder-" + props.color}>
<p>Something here.</p>
{props.children} {/* you can insert JSX here! */}
<p>Something else here.</p>
</div>
);
}
function WelcomeDialog() {
return (
<FancyBorder color="blue">
{/* you can insert JSX here! */}
<h1 className="Dialog-title">Welcome</h1>
<p className="Dialog-message">Thank you for visiting our spacecraft!</p>
{/* you can insert JSX here! */}
</FancyBorder>
);
}
If you want custom "holes" in a component, you can do that too:
function SplitPane(props) {
// custom props let you control where the JSX "holes" are!
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left} {/* you can insert JSX here! */}
</div>
<div className="SplitPane-right">
{props.right} {/* you can insert JSX here! */}
</div>
</div>
);
}
function App() {
return (
{/* custom props let you control where the JSX "holes" are! */}
<SplitPane
left={<Contacts />}
right={<Chat />}
/>
);
}
https://css-tricks.com/what-are-higher-order-components-in-react/
// higher-order component: takes a component and returns a component (in this case, with modified props)
const hoc = (WrappedComponent) => (props) => {
return (
<div>
<WrappedComponent {...props}>
{props.children.toUpperCase()}
</WrappedComponent>
</div>
);
};
// component to put into the “hoc”:
const Username = (props) => <div>{props.children}</div>;
// “hoc” being created:
const UpperCaseUsername = hoc(Username);
// “hoc” being used:
const App = () => (
<div>
<UpperCaseUsername>Kingsley</UpperCaseUsername>
</div>
);
May replace higher-order components and nesting.
https://css-tricks.com/intro-to-react-hooks/
componentDidMount() {
// A
}
componentWillUnmount() {
// B
}
useEffect(() => {
// A
return () => {
// B
};
}, []);
https://github.com/hchiam/react-jexcel-redux/commit/90db044627780ed6262f5e29bb61a24390a4d4b3
Easy solution: https://github.com/Swizec/useAuth
https://github.com/hchiam/learning-react-2dnote
https://github.com/hchiam/learning-react-tdd
https://jamesknelson.com/5-types-react-application-state
- Data
- Communication
- Control
- Session
- Location
Worth a read: https://www.joshwcomeau.com/react/why-react-re-renders but for a quick summary/reminder, see the interactive graphs, but here are my key take-aways:
- when component re-renders, it re-renders all its children by default,
- even if they aren't actually affected by the change in props by default,
- but with
React.memo
you can create pure-components that let you avoid/minimize that (well, certain re-renders) by diffing props instead of creating the entire component to then find diffs in that - "The React team is actively investigating whether it's possible to “auto-memoize” code during the compile step. It's still in the research phase, but early experimentation appears promising." (more info: https://www.youtube.com/watch?v=lGEMwh32soc)
- but with
- even if they aren't actually affected by the change in props by default,
Examples:
<button
data-custom-attribuet="some-value"
aria-label="Close dialog"
>
Remember class
is className
and for
is htmlFor
because JSX will inject JS into slots!
https://transform.tools/html-to-jsx
JSX looks like a template language, but JSX transpiles to JS and then HTML which then is more dynamic, and doesn't invent a totally different language, and can leverage existing JS.
https://github.com/hchiam/learning-react-error-boundaries
SSR (Server Side Rendering) and React Server Components: https://www.joshwcomeau.com/react/server-components/
- React Scan to get render hints etc to dig into performance sinks: https://www.youtube.com/watch?v=ROKRTZ_xCgo
- avoid interacting with the DOM directly, and use React's abstraction to let React handle DOM manipulation, cleanup, and optimization for you
- (e.g., don't use
querySelector
) - (e.g., replace jQuery way of doing things with React conventions)
- (e.g., don't use
- React
key
like in<div key={valueThatChanges} className={styles.animate}>
can be used to make thediv
element re-render, and hence also re-run any animation on it set by class.animate
- btw,
key
is a reserved keyword in React, and looks like a component prop, but is really like an element ID (key
won't show up in the component'sprop
s) key
is better off as = some unique ID, not simply as array index (key
= array index can run into some weird bugs)key
must be top-level element in listkey
only has to be unique within a list
- btw,
- React
useEffect
is meant for synchronizing React with something outside of React (e.g. API call). - Motion (previously Framer Motion) has default springy/natural animations
- code example:
import { motion } from 'framer-motion'; function SomeComponent() { return <motion.div animate={{ y: 10 }} initial={false} // set false so it doesn't include enter animation on load transition={{ // not required type: 'spring', // this is the default, and so i don't really need transition here at all damping: 25, // i like the spring default, so i don't need this either stiffness: 200, // i like springy default, so i don't need this either }} />; }
- use
as
prop to combine Motion with styled-components:or composition by wrapping theconst RedButton = styled.button` color: red; `; <RedButton as={motion.button}>
motion.[...]
in astyled(...)
:const RedButton = styled(motion.button)` color: red; `;
- code example:
- when to use Higher-Order-Components (HOCs) vs when to use Hooks in React: https://www.patterns.dev/react/hoc-pattern/
- HOCs:
- repeated UNcustomized when used by each component
- can work standalone
- Hooks:
- behaviour needs to be customized when used by each component
- not spread throughout the app, only a few components use it
- it adds many properties to a component
- watch out for overriding/colliding prop names! consider merging with something like:
const style = { margin: '1rem', ...props.style };
- HOCs:
- hooks > classes: https://www.patterns.dev/react/hooks-pattern/
- render props pattern: https://www.patterns.dev/react/render-props-pattern/ (see pros and cons section)
props.render(data)
so you can pass HTML as a callback to a component's props, and have it render with its own data- with
<ComponentName render={(value) => (<SomethingElse value={value}/>)}/>
- with
- or
props.children(data)
- with
<ComponentName>{(value) => (<SomethingElse value={value}/>)}<ComponentName/>
- with
- good reusability and able to share data between components without "lifting" state
- note:
count && <element>
could render0
if count is 0- so it should instead be:
count > 0 && <element>
- so it should instead be: