Skip to content

Instantly share code, notes, and snippets.

@heaversm
Last active May 6, 2020 15:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heaversm/1d16c29fd495fd187295b0af584f7316 to your computer and use it in GitHub Desktop.
Save heaversm/1d16c29fd495fd187295b0af584f7316 to your computer and use it in GitHub Desktop.
Common React Functionality
/* reusable function to update any form input value with state */
state = {
title: ''
}
handleChange = (e)=>{
const {name, type, value} = e.target;
console.log({name,type,value}); //gives keys to your console log values when you put brackets around them!
const val = type === 'number' ? parseFloat(value) : value; //converts numbers from strings
this.setState({[name]: val}); //allows us to use a single function for all inputs with `[name]`
}
render() {
return (
<input type="text" id="title" name="title" placeholder="Title" required value={this.state.title} onChange={this.handleChange} />
)
}
/*using a timer in react that only initializes once, via functional update:*/
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(c => c + 1); // ✅ This doesn't depend on `count` variable outside
}, 1000);
return () => clearInterval(id);
}, []); // ✅ Our effect doesn't use any variables in the component scope
return <h1>{count}</h1>;
}
/* Read latest props at any time within react */
function Example(props) {
// Keep latest props in a ref.
const latestProps = useRef(props);
useEffect(() => {
latestProps.current = props;
});
useEffect(() => {
function tick() {
// Read latest props at any time
console.log(latestProps.current);
}
const id = setInterval(tick, 1000);
return () => clearInterval(id);
}, []); // This effect never re-runs
}
/* only run an expensive function update in react when certain props change by wrapping that function in useMemo: */
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
/*only render expensive child components if a certain prop changes: */
function Parent({ a, b }) {
// Only re-rendered if `a` changes:
const child1 = useMemo(() => <Child1 a={a} />, [a]);
// Only re-rendered if `b` changes:
const child2 = useMemo(() => <Child2 b={b} />, [b]);
return (
<>
{child1}
{child2}
</>
)
}
/*prevent a useState function from running on ever render: */
//this runs every render:
function Table(props) {
// ⚠️ createRows() is called on every render
const [rows, setRows] = useState(createRows(props.count));
// ...
}
//this doesn't:
function Table(props) {
// ✅ createRows() is only called once
const [rows, setRows] = useState(() => createRows(props.count));
// ...
}
/*same deal if you want to avoid recreating a useRef initial value:*/
//this runs every render
function Image(props) {
// ⚠️ IntersectionObserver is created on every render
const ref = useRef(new IntersectionObserver(onIntersect));
// ...
}
//this doesn't:
function Image(props) {
const ref = useRef(null);
// ✅ IntersectionObserver is created lazily once
function getObserver() {
if (ref.current === null) {
ref.current = new IntersectionObserver(onIntersect);
}
return ref.current;
}
// When you need it, call getObserver()
// ...
}
/* dispatch a state update to a parent from a deep child without passing down props: */
const TodosDispatch = React.createContext(null);
function TodosApp() {
// Note: `dispatch` won't change between re-renders
const [todos, dispatch] = useReducer(todosReducer);
return (
<TodosDispatch.Provider value={dispatch}>
<DeepTree todos={todos} />
</TodosDispatch.Provider>
);
}
//Any child in the tree inside TodosApp can use the dispatch function to pass actions up to TodosApp:
function DeepChild(props) {
// If we want to perform an action, we can get dispatch from context.
const dispatch = useContext(TodosDispatch);
function handleClick() {
dispatch({ type: 'add', text: 'hello' });
}
return (
<button onClick={handleClick}>Add todo</button>
);
}
/* you can destructure a function param into its component parts, for example if your param is a payload consisting of loading and error states:*/
myDestructuredParams({loading,error}){
//...
}
const args = {
loading: function(){
//...
},
error: function(){
//...
}
}
myDestructuredParams(args);
/* async functions */
uploadFile = async(e) => {
const res = await fetch('https://api.cloudinary.com/v1_1/[user_name]/image/upload', {
method: 'POST',
body: data
});
}
/* Disable ES Lint Line */
// eslint-disable-line react-hooks/exhaustive-deps
/* GET PREV PROPS OR STATE */
function Counter() {
const [count, setCount] = useState(0);
const prevCount = usePrevious(count); return <h1>Now: {count}, before: {prevCount}</h1>;
}
function usePrevious(value) { const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment