Events and its handling
This is the place to have side effects
Event handler
- defined inside your components.
- names that start with handle, followed by the name of the event.
- pass function(or event handler) to component to
<button onClick={handleClick}>
or<button onClick={() => alert('...')}>
. Do not use<button onClick={handleClick()}>
because it will execute immediately during rendering, which is not desired. - event handler props should start with on
Event propagation
- event “bubbles” or “propagates” up the tree (ie, child to parent. except onScroll) .
- you can stop propagation using:
<button onClick={e => { e.stopPropagation(); onClick(); }}>
- use onClickCapture , if we need to catch all events on child elements, even if they stopped propagation (we probably wont use this).
Handing default behavior
- Some browser events have default behavior associated with them we can control that by handling propogation.
<form onSubmit={e => { e.preventDefault(); alert('Submitting!'); }}>
State: a component’s memory
- Data that changes over time.
- Component-specific memory (specific for each declaration(or use) of components).
- More about useState.
Difference between local and state variables
-
Local variables don’t persist between renders (state persists between renders).
-
Changes to local variables won’t trigger renders (change of state will trigger re-render).
-
const [index, setIndex] = useState(0); [] <- array destructuring
Hook
- Hooks are special functions that are only available while React is rendering.
- Hooks can only be called at the top level of your components or your own Hooks (can’t call Hooks inside conditions, loops, or other nested functions.).
- useState -> telling React that you want this component to remember something.
How hooks works? pugin to enforce rules of hooks how react know which state to return
How react exececutes our code
- Triggering a render.
- Initial render
const root = createRoot(document.getElementById('root')) root.render(<Image />);
. read more - Render due to state change.
- Initial render
- Rendering (aka calling) the component.
- Committing to the DOM.
- React used appendChild to put all dom nodes.
- For re-renders only changes in the nodes are renderd.
Behaviour of state
- State behaves like a snapshot.
- Changing state will trigger re-render.
- We can’t change state of running code; to do that, use an updater function
setScore(score + 1); --change to--> setScore(s => s + 1);
. Updater function lets you queue multiple state updates. - props, event handlers, and local variables were all calculated using its state at the time of the render.
- state lives outside of the function we call.
<button onClick={() => { setNumber(number + 1); setNumber(number + 1); setNumber(number + 1); }}>+3</button> --- this is a good example of how snapshot of state is passed for rendering . if number = 0 initially . --- react "see" it like code shown below. <button onClick={() => { setNumber(0 + 1); setNumber(0 + 1); setNumber(0 + 1); }}>+3</button>
- A state variable’s value never changes within a render, even if its event handler’s code is asynchronous.
- React waits until all code in the event handlers has run before processing your state updates.
Batch (multiple) state updates
- React won’t re-render until after your event handler, and any code in it, completes. This behavior, also known as batching.
- React does not batch across multiple intentional events like clicks.
- To update same state multiple time use updater function
- remember how queued updates are done by react.
- State updates are added to a queue.
- React processes each item in the state queue in order.(Direct values replace the current state.)
- Updater functions calculate the new state based on the current state.
- React stores the final result from processing the queue and returns it from useState.
Objects as state
- Don’t manipulate (change or mutate) object and array directly (React might not ‘see’ the changes you did to the object).
- Create a copy of the existing one and update it (use spread operator).
setPerson({ ...person, // Copy the old fields firstName: e.target.value // But override this one });
usage of spead operator(shallow copy)
setPerson({ ...person, // Copy other fields artwork: { // but replace the artwork ...person.artwork, // with the same one city: 'New Delhi' // but in New Delhi! } });
updating nested property using spread operator.
“There is no nested object. Its two different objects ,we can say that property of one object is pointing to another object.
-
we can use
[]
to update a dynamic name of a propertyfunction handleChange(e) { setPerson({ ...person, [e.target.name]: e.target.value }); }
-
useImmer to handle object states.
Arrays as state
- Handle like an object.
- array methods we should consider to update state.
Operation | Avoid (Mutates the Array) | Prefer (Returns a New Array) |
---|---|---|
Adding | push , unshift | concat , [...arr] |
Removing | pop , shift , splice | filter , slice |
Replacing | splice , arr[i] = ... (assignment) | map |
Sorting | reverse , sort | Copy the array first |
- you can see its usage in here and sample app