[🚧 Work In Progress v1.0] The fastest way to build cross-container application.
âš¡ Fast: blazing fast virtual DOM.
🎯 Tiny: ~8 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
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 DomDriver from 'driver-dom';
import Hello from './Hello';
render(<Hello name="world" />, document.body, { driver: DomDriver });
- 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 } from 'rax';
import { useRouter, push } from 'rax-use-router';
import Foo from './Foo';
const routes = [{
path: '/home',
children: [
{
path: '', // www.example.com/home
action: () => <>
<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
action: (params) => <>
<p>{params.username}</p>
<button onClick={ () => push('/home') }>Go home</button>
</>
}
]},
{
path: '/bar',
children: [
{
path: '', // www.example.com/bar
action: () => import(/* webpackChunkName: "bar" */ './Bar'),
},
],
},
{
path: '/foo', // www.example.com/foo
action: () => <Foo />,
},
];
export default function Example() {
var component = useRouter(routes, '/hi');
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>
}
- 🚥 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-redux
module 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 lint
checks the code style.npm test
runs the complete test suite.npm test -- --watch
runs an interactive test watcher.npm test <pattern>
runs tests with matching filenames.npm run build
createslib
anddist
folder with all the packages.npm start
start local server withexamples
folder.
![]() @yuanyan Core |
![]() @imsobear Development |
![]() @yacheng Universals & Components |
![]() @boiawang Loaders & Plugins |
![]() @wssgcg1213 DSL Runtimes & Loaders |