Skip to content

Instantly share code, notes, and snippets.

@Offirmo
Last active February 11, 2025 05:23
Show Gist options
  • Save Offirmo/3a4df6943c3f5363d08a1c7a6e80a07d to your computer and use it in GitHub Desktop.
Save Offirmo/3a4df6943c3f5363d08a1c7a6e80a07d to your computer and use it in GitHub Desktop.
[🔷TS -- React -- recipes] #react #frontend
// https://react.dev/learn/typescript
import React from 'react'
// really? or import * as React from 'react' ?? https://github.com/facebook/react/pull/18102 ALSO https://www.typescriptlang.org/tsconfig/#allowSyntheticDefaultImports
// or not even need to import React? https://parceljs.org/recipes/react/#jsx
import React, { Component } from 'react'
// (from .d.ts)
type ReactNode =
| ReactElement
| string
| number
| bigint
| Iterable<ReactNode>
| ReactPortal
| boolean
| null
| undefined
| Promise<AwaitedReactNode>;
interface ReactElement {
type: T;
props: P;
key: string | null;
}
// https://react.dev/blog/2024/12/05/react-19
// https://react.dev/blog/2022/03/29/react-v18
// https://legacy.reactjs.org/blog/2020/10/20/react-v17.html
// https://reactjs.org/blog/2018/10/23/react-v-16-6.html
// https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
//////////////////////////////////////////////////////////////////
// JSX
;(
<>
<div key="foo" className="foo bar" debug-id="foo">
</div>
</>
);
// If an attribute name is not a valid JS identifier (like a data-* attribute), it is not considered to be an error if it is not found in the element attributes type.
// https://stackoverflow.com/a/76230903/587407
// general guidance for fast refresh: https://parceljs.org/recipes/react/#tips
// - Avoid class components – Fast Refresh only works with function components (and Hooks).
// - Export only React components – If a file exports a mix of React components and other types of values, its state will be reset whenever it changes. To preserve state, only export React components and move other exports to a different file if possible.
// - Avoid unnamed default exports – Declaring components using a default exported arrow function will cause state to be reset when it is changed. Use a named function, or assign the arrow function to a variable instead.
// - Keep entry components in their own files – Entry components should be in a separate file from the one that calls createRoot or they will be remounted on every change.
//////////////////////////////////////////////////////////////////
// function components
interface Props {
children?: ReactNode
}
function Foo({ children = <DefaultMenu /> }: Props) => { ... }
//////////////////////////////////////////////////////////////////
// init
// https://react.dev/reference/react/StrictMode
import { StrictMode, Suspense } from 'react'
import { createRoot } from 'react-dom/client'
// https://react.dev/blog/2024/04/25/react-19-upgrade-guide#errors-in-render-are-not-re-thrown
const root = createRoot(document.getElementById('root'), {
onUncaughtError: (error, errorInfo) => {
// ... log error report
},
onCaughtError: (error, errorInfo) => {
// ... log error report
}
})
root.render(
<StrictMode>
<App />
</StrictMode>
)
//////////////////////////////////////////////////////////////////
// Class components
// considered legacy but still useful
// https://react.dev/reference/react/Component
interface Props { /***/ }
interface State { /***/ }
export class Foo extends Component<Props, State> {
constructor(props) {
super(props)
this.state = { /***/ }
}
render() {
console.log("🔄 Foo render", this.props, this.state);
const { … } = this.props
const stackElements: ReactNode[] = [];
return <>
Hello, world!
{stackElements}
</>
}
}
//////////////////////////////////////////////////////////////////
// refs
const [ref, setRef] = useState();
const ... = ref?...
return (
<svg ref={newRef => setRef(newRef)}
// context https://reactjs.org/blog/2018/03/29/react-v-16-3.html#official-context-api
// portals https://reactjs.org/blog/2017/09/26/react-v16.0.html#portals
// DOM attributes https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html
// pointer events https://reactjs.org/blog/2018/05/23/react-v-16-4.html#pointer-events
// https://reactjs.org/blog/2016/11/16/react-v15.4.0.html#profiling-components-with-chrome-timeline
//////////////////////////////////////////////////////////////////
// lazy loading / code splitting https://parceljs.org/recipes/react/#code-splitting
const Profile = React.lazy(() => import('./Profile'));
//////////////////////////////////////////////////////////////////
// https://github.com/facebook/prop-types
Foo.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
analyticsClient: PropTypes.shape({ // also PropTypes.exact(
sendTrackEvent: PropTypes.func.isRequired,
sendUIEvent: PropTypes.func.isRequired,
sendScreenEvent: PropTypes.func.isRequired
}).isRequired,
optionalNode: PropTypes.node, // Anything that can be rendered: numbers, strings, elements or an array (or fragment) containing these types.
optionalElement: PropTypes.element,
requiredAny: PropTypes.any.isRequired,
}
Foo.defaultProps = {
lang: 'en-US',
}
//////////////////////////////////////////////////////////////////
var createReactClass = require('create-react-class');
var Component = createReactClass({
mixins: [MixinA],
render() {
return <Child />;
}
});
//////////////////////////////////////////////////////////////////
// https://reactjs.org/docs/react-api.html#reactchildrenonly
React.Children.only(children)
this.forceUpdate();
this.setState({})
this.setState(state => ({
reading_string: false,
input_resolve_fn: null,
}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment