Skip to content

Commit

Permalink
update custom renderer docs
Browse files Browse the repository at this point in the history
  • Loading branch information
brainkim committed Jul 21, 2020
1 parent 66fc189 commit 25468d2
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 19 deletions.
8 changes: 4 additions & 4 deletions website/guides/06-special-props-and-tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ You can still use the `className` and `htmlFor` props as well, but using the for

Crank provides four element tags which have special meaning to the renderer, and affect element diffing and rendering output in various ways.

### Fragment
### `Fragment`
Crank provides a `Fragment` tag, which allows you to render multiple children into a parent without wrapping them in another DOM node. Under the hood, iterables which appear in the element tree are also implicitly wrapped in a `Fragment` element by the renderer.

```jsx
Expand All @@ -158,7 +158,7 @@ console.log(document.body.innerHTML);
// "<div>Sibling 1</div><div>Sibling 2</div>"
```

### Copy
### `Copy`
It‘s often fine to rerender Crank components, because elements are diffed, persistent between renders, and unnecessary mutations usually avoided. However, you might want to prevent a child from updating when the parent rerenders, perhaps because a certain prop hasn’t changed, because you want to batch updates from the parent, or as a performance optimization. To do this, you can use the `Copy` tag to indicate to Crank that you don’t want to update a previously rendered element in that same position.

```jsx
Expand Down Expand Up @@ -190,7 +190,7 @@ function memo(Component) {

In this example, `memo` is a higher-order component, a function which takes a component and returns a component. This wrapper component compares old and new props and yields a `Copy` element if every prop is shallowly equal. A `Copy` element can appear anywhere in an element tree to prevent rerenderings, and the only props `Copy` elements take are the `crank-key` and `crank-ref` props, which work as expected.

### Portal
### `Portal`
Sometimes you may want to render into a DOM node which isn’t the current parent element, or even a part of the currently rendered DOM tree. You can do this with the `Portal` tag, passing in a DOM node as its `root` prop. The Portal’s children will be rendered into the specified root element, just as if Renderer.render was called with the root value as its second argument.

```jsx
Expand Down Expand Up @@ -219,7 +219,7 @@ console.log(root2.innerHTML);

This tag is useful for creating modals or tooltips, which usually need to be rendered into separate DOM elements at the bottom of the page for visibility reasons. Events dispatched from a `Portal` element‘s child components via the `dispatchEvent` method will still bubble into parent components.

### Raw
### `Raw`
Sometimes, you may want to insert raw HTML or actual DOM nodes directly into the element tree. Crank allows you to do this with the `Raw` element. The `Raw` element takes a `value` prop which is interpreted by the renderer. For the DOM renderer, if `value` is an HTML string, the renderer will parse and insert the resulting DOM nodes. If the value is already a DOM node, Crank will insert them in place.

```jsx
Expand Down
28 changes: 14 additions & 14 deletions website/guides/10-custom-renderers.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Renderer<
- `TScope` is the type of the *scope*, a renderer-specific concept for arbitrary data which can passed down the tree between host elements. Scopes are useful for passing contextual information down the tree to be used when nodes are created; for instance, the DOM renderer uses the scope to pass down information about whether were currently rendering in an SVG element.
- `TRoot` is the type of the root node. This is the type of the second parameter passed to the `Renderer.render` method, and the `root` prop passed to `Portal` elements. It is usually the same type as `TNode` but can vary according to renderer requirements.
- `TResult` describes the type of values made visible to renderer consumers. Any time Crank exposes an internal node, for instance, via the `crank-ref` callback, or as the result of yield expressions in generator components, the renderer can intercept this access and provide something other than the internal nodes, allowing renderers to hide implementation details and provide results which make more sense for a specific environment.
For example, the HTML string renderer has an internal node representation, but converts these nodes to strings before theyre exposed to consumers. This is done because the internal nodes must be referentially unique and mutated during rendering, while JavaScript strings are referentially transparent and immutable. Therefore, the `TResult` of the `HTMLRenderer` subclass is `string`.
For example, the HTML string renderer has an internal node representation, but converts these nodes to strings before theyre exposed to consumers. This is because the internal nodes must be a referentially unique object which is mutated during rendering, while JavaScript strings are referentially transparent and immutable. Therefore, the `TResult` type of the HTML renderer is `string`.

## Methods
The following is a description of the signatures of internal renderer methods and when theyre executed.
Expand All @@ -42,44 +42,46 @@ The following is a description of the signatures of internal renderer methods an

```ts
create(
tag: string | symbol, props: Record<string, any>, scope: TScope
el: Element<string | symbol>, scope: TScope
): TNode;
```

The `create` method is called for each host element the first time the element is committed. The tag and props parameters are the tag and props of the host element which initiated this call, and the scope is the current scope of the element. The return value is the node which will be associated with the host element.
The `create` method is called for each host element the first time the element is committed. This method is passed the current host element and scope, and should return the node which will be associated with the host element. This node will remain constant for the duration that the element is mounted in the tree.

By default, this method will throw a `Not Implemented` error, so custom renderers should always implement this method.

### Renderer.prototype.patch
```ts
patch(
tag: string | symbol, props: Record<string, any>, node: TNode, scope: TScope,
el: Element<string | symbol>, node: TNode,
): unknown;
```

The `patch` method is called for each host element whenever it is committed. The tag and props are the tag and props of the associated host element, the node is the value produced by the `create` method when the value was mounted, and the scope is the current scope of the element.
The `patch` method is called for each host element whenever it is committed. This method is passed the current host element and its related node, and its return value is ignored. This method is useful for mutating nodes whenever the host element is committed.

This method is useful for mutating nodes whenever the host element is committed. Implementation is optional and its return value is ignored.
Implementation of this method is optional for renderers.

### Renderer.prototype.arrange
```ts
arrange(
tag: string | symbol, props: Record<string, any>, parent: TNode | TRoot, children: Array<TNode | string>
el: Element<string | symbol>,
parent: TNode | TRoot,
children: Array<TNode | string>,
): unknown;
```

The `arrange` method is called whenever an elements children have changed. The tag and props are the tag and props of the associated host element, the parent is the value created by the create method for a host node and the `children` are the child values of all the elements direct children. The `arrange` is also called for every root/portal element, so the parent can be of type `TRoot` as well as `TNode`.
The `arrange` method is called whenever an elements children have changed. It is called with the current host element, the host elements related node, and the rendered values of all the elements descendants as an array. In addition to when a host element commits, the `arrange` method may also be called when a child refreshes or otherwise causes the host elements rendered children to change. Because the `arrange` method is called for every root/portal element, the parent can be of type `TRoot` as well as `TNode`.

This method is where the magic happens, and is useful for connecting the nodes of your target environment as an internal tree.

### Renderer.prototype.scope
```ts
scope(
tag: string | symbol, props: Record<string, any>, scope: TScope | undefined
el: Element<string | symbol>, scope: TScope | undefined
): TScope;
```

The `scope` method is called for each host or portal element as elements are mounted or updated. Unlike the other custom renderer methods, the `scope` method is called during the pre-order traversal of the tree, much as components are. The `scope` method is passed the tag and props of the relevant host element, as well as the current scope, and the return value becomes the scope argument passed to the `create` and `scope` method calls for child host elements.
The `scope` method is called for each host or portal element as elements are mounted or updated. Unlike the other custom renderer methods, the `scope` method is called during the pre-order traversal of the tree, much as components are. The `scope` method is passed the current host element and scope, and the return value becomes the scope argument passed to the `create` and `scope` method calls for child host elements.

### Renderer.prototype.escape
```ts
Expand All @@ -101,12 +103,10 @@ By default, the `parse` method returns the string which was passed in.

### Renderer.prototype.dispose
```ts
dispose(
tag: string | symbol, props: Record<string, any>, node: TNode
): unknown
dispose(el: Element<string | symbol>, node: TNode): unknown
```

When a host element is unmounted, we call the `dispose` method with the related host elements tag, props and node. This method is useful if you need to manually release a node or clean up event listeners for garbage collection purposes.
When a host element is unmounted, we call the `dispose` method with the host element and its related node. This method is useful if you need to manually release a node or clean up event listeners for garbage collection purposes.

This method is optional and its return value is ignored.

Expand Down
2 changes: 1 addition & 1 deletion website/guides/11-reference-for-react-developers.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The following are specific equivalents for React methods.
### `setState` and `forceUpdate`
Crank uses generator functions and local variables for local state. Refer to [the section on stateful components](./guides/components#stateful-components).

Crank is not “reactive” in the same sense as React, in that it does not actually track your component’s local state. You can either use `Context.prototype.refresh` to manually refresh the component, much like React’s `forceUpdate` method, or you can use async generator components, which refresh automatically whenever the returned async generator yields.
Crank is not “reactive” in the same sense as React, in that it does not track your component’s local state and rerender when it detects a change. You can either use the context’s `refresh` to manually refresh the component, similar to React’s `forceUpdate` method, or you can use async generator components, which refresh automatically whenever the returned async generator yields.

### `defaultProps`
Crank doesn’t have a `defaultProps` implementation. Instead, you can provide default values when destructuring props. [See the guide on default props](./components#default-props).
Expand Down

0 comments on commit 25468d2

Please sign in to comment.