# react-traverse
**Repository Path**: mirrors_FezVrasta/react-traverse
## Basic Information
- **Project Name**: react-traverse
- **Description**: React Components Magic
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-08
- **Last Updated**: 2026-07-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
react-traverse
==============
`react-traverse` applies the principle of tree traversal to the two kinds of trees present in a React hierarchy:
React **nodes** and React **components**.
### React **node** traversal
`traverse(node, visitor)` transforms a React **nodes** hierarchy into another one
(borrowing its syntax from `babel`). A React node is typically what is returned by a single components `render`
function.
For example, you can replace all `
`s with `
s`:
```js
const replaceDivsWithSpans = (node) => traverse(node, {
DOMElement(path) {
if(path.node.type === 'div') {
return React.createElement(
'span',
path.node.props,
...path.traverseChildren(),
);
}
return React.cloneElement(
path.node,
path.node.props,
...path.traverseChildren(),
);
},
});
replaceDivsWithSpans(This is a span.
)
// will render as:
This is a div.
```
See the full traversal API below.
### React **components** wrapping
`traverse` is notably useful to decorate custom components (either classes extending `React.Component` or stateless
function components). So there is a simple decorator, `wrapRender(transformNode)(component)`, which does exactly what
it says on the tin.
For example, you can reuse `replaceDivsWithSpans` and wrap a component in it:
```js
class Component extends React.Component {
render() {
return This is a span.
;
}
}
const WrappedComponent = wrapRender(replaceDivsWithSpans)(Component);
// will render as:
This is a span.
```
### React **components** traversal
`transformComponents(transformComponent)` transforms a React **components** hierarchy into another one. Think
higher-higher-order components, or decorators on steroids. A React Component is either a class extending
`React.Component` or a stateless functional render function. Not only does it transform the component class you apply
it two, but also recursively to all the subcomponents.
It combines very well with both `traverse` and `wrapRender`, as you can apply node transforms to the **whole**
Virtual DOM tree, not only component-local parts of it.
For example, you can transform ALL the divs of your app into spans:
```js
class Foo extends React.Component {
render() {
return This is foo.
;
}
}
function Bar() {
return
This is bar.
;
}
const TransformedBar = transformComponents(wrapRender(replaceDivsWithSpans))(Bar);
// will render as:
This is bar.
This is foo.
```
For convenience, you can use `transformComponents` on components classes (created using `extends React.Component`), on
stateless function components, or directly on React Elements:
```js
const transform = transformComponents(wrapRender(replaceDivsWithSpans));
// decorator
@transform
class Foo extends React.Component { ... }
// stateless function
const Foo = transform(
() => This is foo.
);
// directly on a ReactElement, eg. in a ReactDOM.render call
ReactDOM.render(transform(
));
```
### Node visitor
The following visitor policies are available:
- `Empty`: `null`, `undefined` or boolean
- `Text`: string or number
- `Fragment`: array of React Nodes
- `DOMElement`: non-component elements (`div`, `span`, etc)
- `ComponentElement`: component elements
If a visitor policy is not provided for a given kind, it defaults to a reasonable behaviour:
- `Empty` and `Text` return the original node
- `Fragment` return a new array in which each node has been traversed
- `DOMElement` and `ComponentElement` return a clone element with the same props,
except the children which have also been traversed.
A visitor is passed a single object, `path`, which has the following properties:
- `path.node`: the original node
- `path.kindOf(node)`: a function which returns the kind of node as a string (`Empty`, `Text`, etc)
- `path.traverse(node, visitor = path.visitor)`: a recursive call to the traversal function
- `path.traverseChildren()`: a shortcut to traverse the children of `path.node`
- `path.visitor`: the visitor object for the current traversal
### `transformComponents` memoization
Calls to `transformComponents(transformComponent)(component)` are memoized using a `WeakMap` to avoid allocating
zillions of closures every time the app is rendered. This assumes `transformComponent` itself is pure (stateless) and
`component` is immutable. This should be the case unless you're doing something very wrong.