代码改变世界

React Native

2021-01-24 14:17  AndrewCja  阅读(183)  评论(0编辑  收藏  举报

React Native

 

 

HOCs
const EnhancedComponent = higherOrderComponent(WrappedComponent);
Use HOCs For Cross-Cutting Concerns
We previously recommended mixins as a way to handle cross-cutting concerns. We’ve since realized that mixins create more trouble than they are worth.
A HOC is a pure function with zero side-effects.

Render Props
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
If you really want a HOC for some reason, you can easily
create one using a regular component with a render prop!
function withMouse(Component) {
return class extends React.Component {
render() {
return (
<Mouse render={mouse => (
<Component {...this.props} mouse={mouse} />
)}/>
);
}
}
}

React.PureComponent
shouldComponentUpdate lifecycle method
consider using immutable objects to facilitate fast comparisons of nested data.

Error Boundaries
A class component becomes an error boundary if it defines either (or both) of the lifecycle methods static getDerivedStateFromError() or componentDidCatch().
React doesn’t need error boundaries to recover from errors in event handlers. Unlike the render method and lifecycle methods, the event handlers don’t happen during rendering. So if they throw, React still knows what to display on the screen. If you need to catch an error inside event handler, use the regular JavaScript try / catch statement.

Forwarding Refs
The second ref argument only exists when you define a component with React.forwardRef call. Regular function or class components don’t receive the ref argument, and ref is not available in props either. Ref forwarding is not limited to DOM components. You can forward refs to class component instances, too.

Refs
You may not use the ref attribute on function components because they don’t have instances.
If you want to allow people to take a ref to your function component, you can use forwardRef.
You can pass callback refs between components like you can with object refs that were created with React.createRef().
We advise against it because string refs have some issues, are considered legacy. If you’re currently using this.refs.textInput to access refs, we recommend using either the callback pattern or the createRef API instead.

Uncontrolled Components
Since an uncontrolled component keeps the source of truth in the DOM, it is sometimes easier to integrate React and non-React code when using uncontrolled components.

Web Components
Web Components often expose an imperative API. For instance, a video Web Component might expose play() and pause() functions.

JSX
Each JSX element is just syntactic sugar for calling React.createElement().

 


Hooks
The useSomething naming convention is how our linter plugin is able to find bugs in the code using Hooks.

useState
However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it.
The state of each component is completely independent. Hooks are a way to reuse stateful logic, not state itself.
Each call to a Hook has a completely isolated state — so you can even use the same custom Hook twice in one component.

useEffect
Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.
In React class components, the render method itself shouldn't cause side effects. It would be too early — we typically want to perform our effects after React has updated the DOM. By using this Hook, you tell React that your component needs to do something after render. You can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.
In React class components, the render method itself shouldn’t cause side effects. It would be too early — we typically want to perform our effects after React has updated the DOM. we put side effects into componentDidMount and componentDidUpdate.
React would unsubscribe from our ChatAPI when the component unmounts, as well as before re-running the effect due to a subsequent render. (If you want, there’s a way to tell React to skip re-subscribing if the props.friend.id we passed to ChatAPI didn’t change.)
Experienced JavaScript developers might notice that the function passed to useEffect is going to be different on every render. This is intentional. In fact, this is what lets us read the count value from inside the effect without worrying about it getting stale. Every time we re-render, we schedule a different effect, replacing the previous one. In a way, this makes the effects behave more like a part of the render result — each effect “belongs” to a particular render.
This behavior ensures consistency by default and prevents bugs that are common in class components due to missing update logic.
You can tell React to skip applying an effect if certain values haven’t changed between re-renders. To do so, pass an array as an optional second argument to useEffect:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes
In the future, the second argument might get added automatically by a build-time transformation.

Rules of Hooks
Don’t call Hooks inside loops, conditions, or nested functions. Don’t call Hooks from regular JavaScript functions.
Call Hooks from React function components.
Call Hooks from custom Hooks (we’ll learn about them on the next page).

useLayoutEffect
Unlike componentDidMount or componentDidUpdate, effects scheduled with useEffect don’t block the browser from updating the screen. This makes your app feel more responsive. The majority of effects don’t need to happen synchronously. In the uncommon cases where they do (such as measuring the layout), there is a separate useLayoutEffect Hook with an API identical to useEffect.

useContext
useContext lets you subscribe to React context without introducing nesting.
useContext(MyContext) is equivalent to static contextType = MyContext in a class, or to <MyContext.Consumer>. You still need a <MyContext.Provider> above in the tree to provide the value for this context.

useReducer
useReducer lets you manage local state of complex components with a reducer:
useReducer also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks.
React doesn’t use the state = initialState argument convention popularized by Redux. The initial value sometimes needs to depend on props and so is specified from the Hook call instead. If you feel strongly about this, you can call useReducer(reducer, undefined, reducer) to emulate the Redux behavior, but it's not encouraged.

useCallback
useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).
The array of dependencies is not passed as arguments to the callback. Conceptually, though, that’s what they represent: every value referenced inside the callback should also appear in the dependencies array. In the future, a sufficiently advanced compiler could create this array automatically.

 


RTK
"Mutable" Update Logic:
Notice that the addTodo reducer is calling state.push(). Normally, this is bad, because the array.push() function mutates the existing array, and Redux reducers must never mutate state!.
However, createSlice and createReducer wrap your function with produce from the Immer library. This means you can write code that "mutates" the state inside the reducer, and Immer will safely return a correct immutably updated result.
Normal immutable update logic tends to obscure what you're actually trying to do because of all of the extra copying that has to happen. Here, the intent should be much more clear: we're adding an item to the end of an array, and we're modifying a field in a todo entry.

There are several reasons why you must not mutate state in Redux:
It causes bugs, such as the UI not updating properly to show the latest values
It makes it harder to understand why and how the state has been updated
It makes it harder to write tests
It breaks the ability to use "time-travel debugging" correctly
It goes against the intended spirit and usage patterns for Redux

 

 

 

 

 

 

 

 

useRef
This works because useRef() creates a plain JavaScript object. The only difference between useRef() and creating a {current: ...} object yourself is that useRef will give you the same ref object on every render.
// Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.
// Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead.
const ref = useRef(new IntersectionObserver(onIntersect)); //IntersectionObserver is created on every render
// useRef does not accept a special function overload like useState. Instead, you can write your own function that creates and sets it lazily:

custom Hooks
// Traditionally in React, we’ve had two popular ways to share stateful logic between components: render props and higher-order components. We will now look at how custom Hooks solve many of the same problems without forcing you to add more components to the tree.
// Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.

useReducer
// The need to manage local state with a reducer in a complex component is common enough that we've built the useReducer Hook right into React.

// Forwarding Refs
// That’s because ref is not a prop. Like key, it’s handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component.
// This means that refs intended for our FancyButton component will actually be attached to the LogProps component:

// Components
We recommend naming props from the component’s own point of view rather than the context in which it is being used.

// Lifecycle
We want to set up a timer whenever the Clock is rendered to the DOM for the first time. This is called “mounting” in React.
We also want to clear that timer whenever the DOM produced by the Clock is removed. This is called “unmounting” in React.
We can declare special methods on the component class to run some code when a component mounts and unmounts:

// State
// Do Not Modify State Directly, it will not re-render a component.
// Wrong, this.state.comment = 'Hello';
// Correct, this.setState({comment: 'Hello'});
// The only place where you can assign this.state is the constructor.
// State Updates May Be Asynchronous
// React may batch multiple setState() calls into a single update for performance.
// Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
// To fix it, use a second form of setState() that accepts a function rather than an object.
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
// State Updates are Merged. When you call setState(), React merges the object you provide into the current state.
// The merging is shallow, so this.setState({comments}) leaves this.state.posts intact, but completely replaces this.state.comments.

// Handling Events
React events are named using camelCase, rather than lowercase.
With JSX you pass a function as the event handler, rather than a string.
For example, the HTML:
<button onclick="handleClick()">
Activate Lasers
</button>
is slightly different in React:
<button onClick={handleClick}>
Activate Lasers
</button>
Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.
We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.

// Conditional Rendering
// Note that returning a falsy expression will still cause the element after && to be skipped but will return the falsy expression. In the example below, <div>0</div> will be returned by the render method.
render() {
const count = 0;
return (
<div>
{ count && <h1>Messages: {count}</h1>}
</div>
);
}

// useEffect
Mutations, subscriptions, timers, logging, and other side effects are not allowed inside the main body of a function component (referred to as React's render phase). Doing so will lead to confusing bugs and inconsistencies in the UI.
// The default behavior for effects is to fire the effect after every completed render. That way an effect is always recreated if one of its dependencies changes.
// However, this may be overkill in some cases, like the subscription example from the previous section. We don’t need to create a new subscription on every update, only if the source prop has changed.
// To implement this, pass a second argument to useEffect that is the array of values that the effect depends on.
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.
If you pass an empty array ([]), the props and state inside the effect will always have their initial values.

// useMemo
Remember that the function passed to useMemo runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering. For example, side effects belong in useEffect, not useMemo.
// The useMemo Hook makes it easier to control when individual children update, reducing the need for pure components.
// Conveniently, useMemo also lets you skip an expensive re-render of a child. Only re-rendered if `a` changes:
const child1 = useMemo(() => <Child1 a={a} />, [a]);

How do I implement shouldComponentUpdate?
// You can wrap a function component with React.memo to shallowly compare its props:
// It's not a Hook because it doesn't compose like Hooks do. React.memo is equivalent to PureComponent, but it only compares props. (You can also add a second argument to specify a custom comparison function that takes the old and new props. If it returns true, the update is skipped.)

useState
// To avoid re-creating the ignored initial state, we can pass a function to useState. createRows() is only called once:
// const [rows, setRows] = useState(() => createRows(props.count));

// Optimizing Performance
// If you know that in some situations your component doesn’t need to update, you can return false from shouldComponentUpdate instead, to skip the whole rendering process, including calling render() on this component and below.
// In most cases, instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state.

// JSX
// both of the imports are necessary in this code, even though React and CustomButton are not directly referenced from JavaScript:
import React from 'react';
import CustomButton from './CustomButton';
function WarningButton() {
// return React.createElement(CustomButton, {color: 'red'}, null);
return <CustomButton color="red" />;
}
const Button = props => {
const { kind, ...other } = props; // rest parameter
const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
return <button className={className} {...other} />; // object spread operation
};
// You can see that it passes an onClick and children props.
To fix this, make sure that the expression before && is always boolean:
<div>
{props.messages.length > 0 &&
<MessageList messages={props.messages} />
}
</div>

// uncontrolled components
<input type="file" />
// Because its value is read-only, it is an uncontrolled component in React. Use ref to interact.
Conversely, if you want a value like false, true, null, or undefined to appear in the output, you have to convert it to a string first:
<div>
My JavaScript variable is {String(myVariable)}.
</div>

style
// Result style: '10px'
<div style={{ height: 10 }}>
Hello World!
</div>
// Result style: '10%'
<div style={{ height: '10%' }}>
Hello World!
</div>
// Certain ones remain unitless (eg zoom, order, flex). A complete list of unitless properties can be seen here.

 

 

 

 

Material-UI
@material-ui/system works with most CSS-in-JS libraries, including JSS, styled-components, and emotion.
If you are already using @material-ui/core, we encourage you to start with the JSS solution to minimize bundle size.