[🚧 Work In Progress v1.0] The fastest way to build cross-container application.
âš¡ Fast: blazing fast virtual DOM.
🎯 Tiny: ~7 KB minified + gzipped.
🎨 Universal: works with DOM, Weex, Node.js, Mini-program, WebGL and could works more container that implement driver specification.
Install the Rax CLI tools to init project:
$ npm install rax-cli -g
$ rax init <YourProjectName>Start local server to launch project:
$ cd YourProjectName
$ npm run start<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/[email protected]/dist/rax.js"></script>
<script src="https://unpkg.com/[email protected]/dist/driver-dom.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// @jsx Rax.createElement
Rax.render(
<h1>Hello, world!</h1>,
document.getElementById('root'),
{ driver: DriverDOM }
);
</script>
</body>
</html>Each JSX element is just syntactic sugar for calling
createElement(component, props, ...children). So, anything you can do with JSX can also be done with just plain JavaScript.
// Hello.jsx
import {createElement, useState} from 'rax';
export default (props) => {
const [name, setName] = useState(props.name);
const handleClick = () => {
setName('rax');
};
return (
<div style={styles.hello}>
<span style={styles.title} onClick={handleClick}>
Hello {name}
</span>
</div>
);
}
const styles = {
hello: {
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center'
},
title: {
fontSize: '40px',
textAlign: 'center'
}
};// app.js
import {render} from 'rax';
import DriverDOM from 'driver-dom';
import Hello from './Hello';
render(<Hello name="world" />, document.body, { driver: DriverDOM });- createElement(type, [props], [...children])
createElement('div', { id: 'foo' }, createElement('p', null, 'hello world'));- Fragment
<Fragment> <header>A heading</header> <footer>A footer</footer> </Fragment>
- createRef()
const inputRef = createRef(); function MyComponent() { return <input type="text" ref={inputRef} />; }
- forwardRef()
const MyButton = forwardRef((props, ref) => ( <button ref={ref}> {props.children} </button> )); // You can get a ref directly to the DOM button: const ref = createRef(); <MyButton ref={ref}>Click me!</MyButton>;
- useState()
function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
- useEffect()
function Example() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
- useLayoutEffect()
function Example() { const [count, setCount] = useState(0); useLayoutEffect(() => { // Fires in the same phase as componentDidMount and componentDidUpdate }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
- useContext()
// Create a Context const NumberContext = createContext(); function Example() { const value = useContext(NumberContext); return <div>The answer is {value}.</div>; }
- useRef()
function TextInputWithFocusButton() { const inputEl = useRef(null); const onButtonClick = () => { // `current` points to the mounted text input element inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button> </> ); }
- useCallback()
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
- useMemo()
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- useReducer()
const initialState = {count: 0}; function reducer(state, action) { switch (action.type) { case 'reset': return initialState; case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: // A reducer must always return a valid state. // Alternatively you can throw an error if an invalid action is dispatched. return state; } } function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, {count: initialCount}); return ( <> Count: {state.count} <button onClick={() => dispatch({type: 'reset'})}> Reset </button> <button onClick={() => dispatch({type: 'increment'})}>+</button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> </> ); }
- useImperativeHandle()
function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} />; } FancyInput = forwardRef(FancyInput);
- memo()
function MyComponent(props) { /* render using props */ } function areEqual(prevProps, nextProps) { /* return true if passing nextProps to render would return the same result as passing prevProps to render, otherwise return false */ } export default memo(MyComponent, areEqual);
- render(element [, container] [, options] [, callback])
render(<HelloMessage name="world" />, document.body, { driver: DomDriver })
- version
- Children
- Children.map(children, function[(thisArg)])
- Children.forEach(children, function[(thisArg)])
- Children.count(children)
- Children.only(children)
- Children.toArray(children)
- PropTypes
- PropTypes.array
- PropTypes.bool
- PropTypes.func
- PropTypes.number
- PropTypes.object
- PropTypes.string
- PropTypes.symbol
- PropTypes.element
- PropTypes.node
- PropTypes.any
- PropTypes.arrayOf
- PropTypes.instanceOf
- PropTypes.objectOf
- PropTypes.oneOf
- PropTypes.oneOfType
- PropTypes.shape
- isValidElement(object)
- cloneElement(element, [props], [...children])
- createFactory(type)
- createPortal(child, container)
- hydrate(element, container[, callback])
- findDOMNode(component)
- unmountComponentAtNode(container)
- Component
- PureComponent
- createClass()
import { createElement, useMemo } from 'rax';
import usePromise from 'rax-use-promise';
const fetchData = () => fetch('https://httpbin.org/get').then(res => res.json());
function Example() {
const [data, error] = usePromise(useMemo(fetchData));
if (error) {
return <p>error</p>
} else if (data) {
return <p>{data.foo}</p>
}
}import { createElement } from 'rax';
import useFetch from 'rax-use-fetch';
function Example() {
const [data, error] = useFetch('https://httpbin.org/get');
if (error) {
return <p>error</p>
} else if (data) {
return <p>{data.foo}</p>
} else {
return <p>loading</p>
}
}import { createElement, Fragment } from 'rax';
import { route, useComponent, push } from 'rax-use-router';
import Foo from './Foo';
route([{
path: '/home',
routes: [
{
path: '', // www.example.com/home
component: () => <>
<button onClick={() => push('/foo')}>go foo</button>
<button onClick={() => push('/bar')}>go bar</button>
<button onClick={() => push('/home/jack')}>go jack</button>
</>,
},
{
path: '/:username', // www.example.com/home/xxx
component: (params) => <>
<p>{params.username}</p>
<button onClick={ () => push('/home') }>Go home</button>
</>
}
]},
{
path: '/bar',
routes: [
{
path: '', // www.example.com/bar
component: () => import(/* webpackChunkName: "bar" */ './Bar'),
},
],
},
{
path: '/foo', // www.example.com/foo
component: () => <Foo />,
},
]);
export default function Example() {
var component = useComponent('/home');
return component;
}// Foo.jsx
import { createElement } from 'rax';
import { push } from 'rax-use-router';
export default function Foo() {
return <button onClick={ () => push('/home') }>Go home</button>
}// Bar.jsx
import { createElement } from 'rax';
import { push } from 'rax-use-router';
export default function Bar() {
return <button onClick={ () => push('/home') }>Go home</button>
}- driver-dom
- driver-weex
- driver-webgl
- driver-worker
- 🚥 rax-test-renderer: Rax renderer for snapshot testing.
- 💻 rax-server-renderer: Rax renderer for server-side render.
- React Developer Tools: Allow you inspect and modify the state of your Rax components at runtime in Chrome Developer Tools.
- Redux DevTools extension: Provide power-ups for your Redux development workflow.
- Use the
rax-reduxmodule in your app - Simply replace code follow the Redux DevTools extension usage doc
- Use the
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for contributing.
After cloning rax, run npm install to fetch its dependencies.
Run npm run setup link and bootstrap project before development.
Then, you can run several commands:
npm run lintchecks the code style.npm testruns the complete test suite.npm test -- --watchruns an interactive test watcher.npm test <pattern>runs tests with matching filenames.npm run buildcreateslibanddistfolder with all the packages.npm startstart local server withexamplesfolder.
@yuanyan Core |
@imsobear Development |
@yacheng Universals & Components |
@boiawang Loaders & Plugins |
@wssgcg1213 DSL Runtimes & Loaders |















