Last active
May 6, 2020 15:12
-
-
Save heaversm/1d16c29fd495fd187295b0af584f7316 to your computer and use it in GitHub Desktop.
Common React Functionality
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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