# Marko for React Developers React is hugely popular in the JavaScript ecosystem. For many, it's their first introduction to JavaScript itself. It's taught in bootcamps. A large number of companies are using it. That said, we believe there's [compelling reasons]() to choose Marko over React for web sites and applications. If you're joining a <a href="https://clickysoft.com/react-js-development-services/">react js development company</a> or team that's already using Marko, or considering using Marko for a new project, you probably want to know if your React experience or the React experience of your teammates and future hires will transfer and allow you all to be successful quickly. Or, maybe you're wondering if your gained Marko experience help you if you end up on a React project in the future? **The answer is "yes".** Many (most?) concepts in React translate 1:1 to Marko. There are differences for sure, but we'll cover those too. ## JSX https://reactjs.org/docs/jsx-in-depth.html - no wrapping `{}` on attributes - `${}` instead of `{}` for text - no fragments ### Control flow - ternaries vs `<if>` - map vs `<for>` - key => by attribute ### JSX as expressions & props.children - attribute tags - _or does this go under #Components?_ ### Render props https://reactjs.org/docs/render-props.html - tag parameters ## Components - imports vs tag discovery - props - events (https://reactjs.org/docs/handling-events.html) - ## Hooks > **A note on legacy APIs**: React's Hooks is the library's 3rd major API. And in existing apps you may run into older "`class` components" or the even older `React.createClass` API which are still supported. Similarly, Marko supports an older "`class` components" and even older "widgets" api you may see out in the wild. Skip to [Legacy](#Legacy) if you're needing to work with these legacy components and have experience with React's legacy APIs. - tags replace hooks - tags variables - no hook rules ### Equivalents to React's built in hooks #### useState - `<let>` #### useEffect - `<effect>` #### useContext https://reactjs.org/docs/context.html - `<get>`/`<set>` #### useMemo/useCallback - not needed #### useRef - tag variables on dom elements #### useImperativeHandle - `<return>` #### useReducer - not implemented, but here's how you could, which brings us to... ### Custom Hooks - `<return>` - "tree aware" - Good 1:1 example. - Good example where the mental model doesn't exactly match. - ImperativeModal ([tweet]( https://twitter.com/andrewgreenh/status/1488938385595158535?s=21), [playground](https://markojs.com/playground/#NobwRAdghgtgpmAXGAlhAJnAHgOhlAJwGsB7MAGjAAcoAXACyTAHo1Nd9izKBjEiWnAFMAPAEkYVOATooAbnACyJdFAA2zElIgAfHmpIBnODoB8AHQgACKwEECcKwE8SAVyuHXDgPyWbIgCNXWlp+K34AYTUUHiIACgBKKxArfSM4ONoCVzgkgF9TEiIRZiCQ-gtrK0Dg0OtI6NjE5NSDYziAM3VjfNMeKAgeODUSsrrKkokpGVp5JRV1SssRNThaZigeIapBdCsAXisutWNmCbGwhpiiA6s4qEMnQbuk-dNkvxsrTe3d26gAO5QFC0cLaRIAbkseQSlS+VgA8torAxHOYwMpVGp0ctSrUKpZligOvsfnAdnB0HCvgBNKBOBkAQmZuOJpjAeXI4Gg8CYU2ksgUmPUeEIpAo1DojGQzD4kn4QlohmY-Jmc2FalFXAlfAEitEdCyypSDgw0gAQionFY8mdCRAVmtNMjDsdThNVusHIYSGoFLcIK41Bolg7ifstEJqf50PJWg9DPt0VQSARaOp0dH4dVTZgCJb0E59sBPtns3FVOnXu8QKWy-XI9ZXd04FCqvX697fQoK3QoAk2x34Xk6-CALp29vVZixuQTVgdUMiBy0LwQZq1qeN25ZHKDr4rtdWCBwAFWAAKBBIMBQ7TiAH0u37cgca6OD3Afc-bo-P93W3WMJtra7J5GOQA)) example? (in this case passing JSX to a function returned from a hook) ## Additional Concepts - https://reactjs.org/docs/forms.html - https://reactjs.org/docs/uncontrolled-components.html - binding `:=` - https://reactjs.org/docs/forwarding-refs.html - ``` <button/el></button> <return=el/> ``` - https://reactjs.org/docs/reconciliation.html - https://reactjs.org/docs/error-boundaries.html - https://reactjs.org/docs/portals.html - https://reactjs.org/docs/code-splitting.html#reactlazy - https://reactjs.org/docs/profiler.html - Marko doesn't have the concept of "rerendering", and is fine-grained, so a profiler to understand "how often a React application renders" doesn't really make sense. Instead, use the [devtools profiler](https://developer.chrome.com/docs/devtools/evaluate-performance/). ## Legacy ### Class Components #### Props & State - props => input - Marko has `this.setState` (slightly diffrent api from React), but you'll probably see assignment to properties on `this.state` more often. - `input` and `state` in the template, `this.input` and `this.state` in the class #### Lifecycle https://reactjs.org/docs/react-component.html#the-component-lifecycle - constructor => onCreate - didComponentMount => onMount - willComponentUpdate => onRender - didComponentUpdate => onUpdate - shouldComponentUpdate (similar but different, immutable data, etc.) - #### Events https://reactjs.org/docs/handling-events.html - this.emit - on-eventName("methodName") ---- **Lit for React Developers** https://codelabs.developers.google.com/codelabs/lit-2-for-react-devs#0 ---- # The following was copied from an older version of this document: ---- ## Rendering ### Client-side **React** ```js import Hello from './Hello'; import ReactDOM from 'react-dom'; const root = ReactDOM.unstable_createRoot(document.body); root.render(<Hello name="React"/>); ``` **Marko** ```js import hello from './hello.marko'; hello.render({ name:'Marko' }).appendTo(document.body); ``` ## Transpiling **React** Chances are, if you've been using React, you've also been using JSX. JSX is a superset of JS supported through a babel transform. For server-side development, you might be using `babel-register` to allow JSX in your `.js` files: ```js require('babel-register'); require('server.js'); ``` For the client, you're probably using webpack along with `babel-loader`: _webpack.config.babel.js_ ```js export default { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['react'] } } } ] } ``` **Marko** Marko ships with a compiler that transforms its view syntax into a JS module. Marko allows you to use JS inside its view, however, if you need to transpile this JS you will need to configure babel to run on your `.marko` files as well. For server-side development you can use `marko/node-require` to allow you to `require`/`import` `.marko` files: ```js require('marko/node-require'); require('server.js'); ``` For the client, you can use webpack with `marko-loader` and configure it to resolve `.marko` files: _webpack.config.babel.js_ ```js export default { resolve: { extensions: [ '.js', '.marko' ] }, rules: [ { test: /\.marko$/, use: { loader: 'marko-loader' } } ] } ``` ## Components ### Functional Components **React** _Hello.js_ ```jsx export default (props) => ( <h1>Hello {props.name}</h1> ); ``` **Marko** _hello.marko_ ```marko <h1>Hello ${input.name}</h1> ``` ### Stateful Components **React** _Counter.js_ ```jsx export default class Counter { state = { count:0 }; increment = () => this.setState(state => ({ count:state.count+1 })); render() { return ( <div> The current count is {this.state.count} <button onClick={this.increment}>++</button> </div> ); } } ``` **Marko** _hello.marko_ ```marko class { onCreate() { this.state = { count:0 }; } increment() { this.state.count++; } } <div> The current count is ${state.count} <button on-click('increment')>++</button> </div> ``` functional setState ## Project Structure React itself does not prescribe any structure for your application, however, if you've worked on any sufficiently large app, you know having a good structure is important. Private Stateless Functional Components ## Children & Composition **React** ```js const Wrapper = ({ children }) => ( <div class="wrapper">{children}</div> ); ``` ```js import Wrapper from "./Wrapper"; const Wrapper = () => ( <Wrapper>{children}</Wrapper> ); ``` **Marko** Body content is recieved on `input` as `renderBody`. It can be rendered using the `<${dynamic}/>` syntax. ```marko <div class="wrapper"> <{input.renderBody}/> </div> ``` ## HOC **React** A [Higher Order Component](https://reactjs.org/docs/higher-order-components.html) is the technique for reusing component logic that replaced mixins. ```js const App = ({ mouse:{ x, y } }) => ( <h1>The mouse position is ({x}, {y})</h1> ); // Just wrap your component in withMouse and const AppWithMouse = withMouse(App) ``` However, more recently, [render props](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) are concidered a better alternative for reusing component logic. ```js const App = () => ( <Mouse render={({ x, y }) => ( <h1>The mouse position is ({x}, {y})</h1> )/> ); ``` Or, using the default `children` prop: ```js const App = () => ( <Mouse> { ({ x, y }) => ( <h1>The mouse position is ({x}, {y})</h1> ) } </Mouse> ); ``` In this case the `Mouse` component would call it's `children` prop as a function and pass `{ x, y }`. ```js render() { /* ... */ return props.children({ x, y }) } ``` **Marko** Marko supports an equivalent that is similar to render props: tag [parameters](https://markojs.com/docs/syntax/#parameters). ```marko <mouse|{ x, y }|> <h1>The mouse position is (${x}, ${y})</h1> </mouse> ``` In the `<mouse>` component, the `x` and `y` value would be passed as attributes when rendering the body: ```marko <${input.renderBody} x=x y=y/> ``` ## Lifecycle ## Integrating with other modules (jQuery) ## Communication ## Context* ## Events* ## Refs ## Loops & Conditionals ### keys ## Accessibility ### `:scoped` ## Inline JS ## Styling ## Portals* ## Web Components ## Extending* JSX is just a lightweight abstraction over a tree structure used to represent a UI, so in React, you have access to this tree structure. Components can modify their children, you can analyze the component tree with all the VDOM nodes which allows you to do a lot of neat things like ... Marko, however, compiles to an optimized program, so at runtime, your application code is not able to modify or inspect much of the component heirarchy. Instead, Marko gives you the ability to modify the component tree at _compile time_. This may seem scary, but it's just another tree structure... an Abstract Syntax Tree (AST). Working at compile-time gives you the opportunity to do (potentially expensive) calculations before your app even starts. Of course, certain things need to know about the component's input/state and can only be done at runtime, but the compiler allows you to inject code that will run later. The AST/Compiler is not well documented at the moment, however the structure of the nodes are _nearly_ identical to the ESTree spec, so if you've worked with Esprima's or Babel's AST you'll feel right at home. ## PropTypes ## Related Modules ### Routing `react-router` ### State Management Redux, MobX ### Data Fetching Falcor, Apollo, Relay ### Animation ## Developer Tools ### App generators `create-react-app` `next.js` `marko-starter` ### Testing `React TestUtils` `Enzyme` `marko test` ### Browser extensions `React Devtools` `marko-inspector` ### Editor Support