Coder Social home page Coder Social logo

preactjs / preact Goto Github PK

View Code? Open in Web Editor NEW
36.0K 402.0 1.9K 15.97 MB

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.

Home Page: https://preactjs.com

License: MIT License

JavaScript 95.56% TypeScript 2.64% HTML 1.80%
preact jsx react virtual-dom components dom vdom

preact's Introduction

Preact

Fast 3kB alternative to React with the same modern API.

All the power of Virtual DOM components, without the overhead:

  • Familiar React API & patterns: ES6 Class, hooks, and Functional Components
  • Extensive React compatibility via a simple preact/compat alias
  • Everything you need: JSX, VDOM, DevTools, HMR, SSR.
  • Highly optimized diff algorithm and seamless hydration from Server Side Rendering
  • Supports all modern browsers and IE11
  • Transparent asynchronous rendering with a pluggable scheduler

💁 More information at the Preact Website ➞

npm Preact Slack Community OpenCollective Backers OpenCollective Sponsors

coveralls gzip size brotli size

You can find some awesome libraries in the awesome-preact list 😎


Getting Started

💁 Note: You don't need ES2015 to use Preact... but give it a try!

Tutorial: Building UI with Preact

With Preact, you create user interfaces by assembling trees of components and elements. Components are functions or classes that return a description of what their tree should output. These descriptions are typically written in JSX (shown underneath), or HTM which leverages standard JavaScript Tagged Templates. Both syntaxes can express trees of elements with "props" (similar to HTML attributes) and children.

To get started using Preact, first look at the render() function. This function accepts a tree description and creates the structure described. Next, it appends this structure to a parent DOM element provided as the second argument. Future calls to render() will reuse the existing tree and update it in-place in the DOM. Internally, render() will calculate the difference from previous outputted structures in an attempt to perform as few DOM operations as possible.

import { h, render } from 'preact';
// Tells babel to use h for JSX. It's better to configure this globally.
// See https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#usage
// In tsconfig you can specify this with the jsxFactory
/** @jsx h */

// create our tree and append it to document.body:
render(
	<main>
		<h1>Hello</h1>
	</main>,
	document.body
);

// update the tree in-place:
render(
	<main>
		<h1>Hello World!</h1>
	</main>,
	document.body
);
// ^ this second invocation of render(...) will use a single DOM call to update the text of the <h1>

Hooray! render() has taken our structure and output a User Interface! This approach demonstrates a simple case, but would be difficult to use as an application grows in complexity. Each change would be forced to calculate the difference between the current and updated structure for the entire application. Components can help here – by dividing the User Interface into nested Components each can calculate their difference from their mounted point. Here's an example:

import { render, h } from 'preact';
import { useState } from 'preact/hooks';

/** @jsx h */

const App = () => {
	const [input, setInput] = useState('');

	return (
		<div>
			<p>Do you agree to the statement: "Preact is awesome"?</p>
			<input value={input} onInput={e => setInput(e.target.value)} />
		</div>
	);
};

render(<App />, document.body);

Sponsors

Become a sponsor and get your logo on our README on GitHub with a link to your site. [Become a sponsor]

           

Backers

Support us with a monthly donation and help us continue our activities. [Become a backer]


License

MIT

Preact

preact's People

Contributors

38elements avatar aimwhy avatar alexgalays avatar andrewiggins avatar braddunbar avatar cristianbote avatar developit avatar fekete965 avatar forsakenharmony avatar gpoitch avatar greenkeeperio-bot avatar jovidecroock avatar jviide avatar k1r0s avatar kevindoughty avatar marvinhagemeister avatar mkxml avatar mochiya98 avatar natevw avatar nekr avatar pmkroeker avatar prateekbh avatar robertknight avatar rpetrich avatar rschristian avatar shoonia avatar sventschui avatar tanhauhau avatar valotas avatar wardpeet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

preact's Issues

Uncaught error when dangerouslySetInnerHTML attribute is removed

in preact/src/dom/index.js

59  else if (name==='dangerouslySetInnerHTML') {
60      node.innerHTML = value.__html;
61  }

An uncaught error occurs there. When we have dangerouslySetInnerHTML attribute and we remove it, preact/src/vdom/diff.js calls setAccessor to reset the values. Because the value is undefined or null there, the error is thrown

element with attr `key` will not be removed after rerender

My case:

  1. render [node 1, node 2, node 3]
  2. render again with only [node 4]
  3. result in [node 1, node 4, node 2, node 3] in the DOM

all the nodes have different key

if I remove the key, the result will be only [node 4] in the DOM which is as expected

Support findDOMNode

I have a use case where my components are given HTMLElements and I have to append them to the component. My usage is blocked because of this

See it on React Docs

defaultProps and getDefaultProps

Hi!
Currently defaultProps and getDefaultProps is not supported. It is a big problem with making some react components to work with preact. Any plans to implement it?

Normalized onChange event?

In React, the onChange event is normalized across browsers (at least as far back as IE9) so that it fires any time the content of an input changes (e.g. when the user types, backspaces, deletes, etc). Is there a similarly normalized event in preact?

Thanks!

Possible issue with integer keys + heterogeneous siblings

One component named Todo has a render function as following. It will ganerate one Todo list with js codes compiled by React Templates. 2 problems will happen:

  1. If todo.key is integer (which can be zero), add operation would be not work well.
  2. After delete one todo array element of state, UI element can not be removed correspondingly.

I am a fresher of Preact. Maybe they are related to preact/src/vdom/build.js, please check and confirm. Thanks.

<div> 
    <div key="{todo.key}" class="todo-item" rt-repeat="todo in this.state.todos">        
        <img src="src/assets/delete.png"
             onClick="()=>this.remove(todo)"
             title="Remove Todo" />
        <input type="checkbox" checked="{todo.done}" onChange="()=>this.toggleChecked(todoIndex)"/>
        <span rt-class="{done: todo.done}">{todo.value}</span>
    </div>  
    <input key="myinput" class="new-todo" placeholder="What needs to be done?" type="text"
           value="{this.state.edited}"
           onKeyDown="{(e) => this.inputKeyDown(e)}"
           onInput="{this.linkState('edited')}"
           autoFocus="{true}"/>
    <button onClick="()=>this.add()">Add</button><br/>
    <button onClick="()=>this.clearDone()">Clear done</button>
</div>

dangerouslySetInnerHTML not working

How to repro?

var preact = require('preact')
var vnode = preact.h('linter-message-line', {'dangerouslySetInnerHTML': 'Hey there'})
var element = document.createElement('div')
preact.render(vnode, element)
console.log(element.outerHTML) // '<linter-message-line>undefined</linter-message-line>'

Expected behavior

There should have been Hey there as the content

Current behavior

The content is undefined

Background info

I am on OSX with [email protected]. The error is also present in [email protected]

Input type number field clears

When you are syncing an input[type=number] field with state, in Preact, the field clears if a decimal is entered. (e.g. type "10." into the field)

This works as expected in React see this fiddle, or the code pasted below: https://jsfiddle.net/3L94wkx9/

var Hello = React.createClass({
  getInitialState: function () {
    return {
          num: 2
        }
  },

  updateNum: function (e) {
    this.setState({num: e.target.value})
  },

  render: function() {
    return <div>
      <input type="number"
        value={this.state.num}
        onChange={this.updateNum} />
    </div>;
  }
});

A better server rendering API?

Is it possible to do server rendering and repopulate on client side? Do you support async rendering as I mentioned here as one of the issues making React server rendering hard to use?

[Bug] fail to render DOM correctly for component with key

  1. Render [VNode 1, VNode 2, VNode 3]
  2. Update props and render [VNode 1, VNode 2, VNode 4]
  3. Result in DOM [VNode 4] only

All VNodes have unique key
Remove key will work

Real life example: https://github.com/foray1010/Popup-my-Bookmarks/tree/preact

  1. install the extension (npm install, npm install -g gulp, gulp dev, load __dev in chrome extension manager)
  2. Open one folder in the root (let call it folder X)
  3. Open a folder inside that folder X
  4. Open another folder inside folder X
  5. That "another folder" will be the only folder on the right, search field and the root folder will be removed

Browser Support?

All of this is cool and all... but if I can't find out what browser this supports then I won't use it for anything in production 😄

EventSystem

What about SynteticEvents like in React? As I know virtual-dom doesn't have this abstraction

Set up a proper website

It's time Preact got a legitimate website. Feel free to add your vote.

Features

  • Documentation (migrated/copied from wiki)
  • Add-ons & Integrations Gallery
  • Examples
  • "Try It" Editor
  • Demo Gallery

Unmounting a tree of components

Hi,
Today I came about an issue that if I remove a tree of components/elements only the top one will get the componentWillUnmount/componentDidUnmount called

I guess this could happen because components get cached and reused later, tho because of this nested components cannot cleanup timers or dispose of unnecessary resources

maybe https://github.com/developit/preact/blob/5b2ba167cb4e9acc7c0d265358ad7bf056eb46e2/src/vdom/component.js#L235
should be deepHook instead of just hook?

Thanks for any help!

DOM elements duplicated on rerendering

So I have couple of boilerplate projects which show how to use https://github.com/capaj/systemjs-hot-reloader with different frameworks.
I wanted to get one for preact as well, but that proved harder than it should be.
First reason was your custom jsx which I think I can solve with @guybedford but the other one which you might help me with was something that bit me when I rerender a preact app.

I have this very simple hello world app: https://github.com/capaj/jspm-preact/blob/master/public/app.js#L13

All it does is render Hello world. Now when render is called second time(because we reloaded some module and want to refresh the app) it actually appends another Hello world into my 'app' div element. I haven't had any such behaviour with react. React render() always deterministically returns same DOM, overwriting the current elements.

Do you have any reason that this is how preact render method behaves? If not, could you please align the behaviour with react? Then I could drop this little hack: https://github.com/capaj/jspm-preact/blob/master/public/app.js#L16

Thanks for consideration.

What's the catch?

If I can get all the features that react provides, then how can this be smaller? There should be some catch.

Rendering props.children without a wrapper

First of all, great job on Preact !

I noticed the following behavior being inconsistent with react unless there's a preact way of doing it.

It would be nice if we didn't need to wrap props.children with extra div's

Example:

import { h, render, Component } from 'preact';

class TestNotOK extends Component {
    render() {
        return <h1 style="position:absolute; top:0; left:0">Doh! Test No worky!</h1>
    }
}
class TestOK extends Component {
    render() {
        return <h1 style="position:absolute; top:20px; left:0">Doh! Test OK now!</h1>
    }
}

class ProviderNotOK extends Component {
    render() {
        return this.props.children
    }
}

class ProviderOK extends Component {
    render() {
        return <div>{this.props.children}</div>
    }
}

// This does not work
render(<ProviderNotOK>
    <TestNotOK/>
</ProviderNotOK>, document.body);

// This works
render(<ProviderOK>
    <TestOK/>
</ProviderOK>, document.body);

How to make transition animation?

My English is not good, so sorry~~~ 😢

In React ecosystem, I make a easy transition animation by ReactTransitionGroup.

so, by Preact, how i do it ?

I just want easy css transition animation,like enter or leave.

Thank you

preact is awesome project, keep going! 👍

Preact + Custom Element Side Effects

Hi!
I'm trying to use Preact as React replacement in my mobile app. But it seems that Preact does not support Web Components used inside "render". Web Components is used from OnsenUI framework.

I think that i know why it does not work. Preact uses vdom-dom diffing algorithm, React uses vdom-vdom. Onsen's web components changes a DOM (trying to change) and Preact is thinking that it is not right and it's deny it.

Is there any solution with Preact?
Thanks.

Factor into modules

... not separate npm modules or a monorepo or anything, just multiple files. This was originally a project that started on CodePen, and then it graduated to a repo prior to me having worked out a perfect rollup + babel build process. Now, with that or webpack or whatever in place, it should be possible to achieve the same output size using multiple files and a nicer organization.

Attach arbitrary dom elements

Hi,
Is there a supported way of attaching arbitrary dom elements in components? Tried using this.base.appendChild but it seems to cause a mess with the caching of components/elements.

In my case I want to use a datepicker that has nothing to do with preact or react wrapping it in a component for easy use.

Any help appreciated
Thanks

dangerouslySetInnerHTML?

In React, you can set inner HTML with something like:

<div dangerouslySetInnerHTML={{__html: 'my markup'}} />

but preact doesn't seem to support this? Any tips on how to achieve something similar?

Preact incorrectly renders Boolean `false` as text

In react, JS expressions within a node that evaluate to false are skipped, along with null and undefined. Preact skips null and undefined, but renders false as text. It doesn't make sense to keep this behavior, so we should be skipping false.

Ref gives the wrong element after the first render

I have a component called AppPane which has this render method (simplified):

render({children}) {
    return (
      <div ref={el => {
          console.log(el)
          this.rootEl = el
        }}>
        {children}
      </div>
    )
  }

The first console.log correctly logs the div element. But subsequent renders log AppPane. I can still access this.rootEl.base to get access to the div, so I do have a workaround.

component constructor props

Hi !

First of all thanks for this work !

I have a problem when I use props in my constructor from a Component

export default class App extends Component {
  constructor(props) {
    super(props);
  }
}

props are always undefined. So i've found in the source that if i change createComponentFromVNode function like this

function createComponentFromVNode(vnode) {
    console.log('createComponentFromVNode', vnode);
    let props = getNodeProps(vnode);
    let component = componentRecycler.create(vnode.nodeName, props);

    //let props = getNodeProps(vnode);
    console.log('les props', props);
    setComponentProps(component, props, NO_RENDER);
    renderComponent(component, DOM_RENDER);

    // let node = component.base;
    //if (!node._component) {
    //  node._component = component;
    //  node._componentConstructor = vnode.nodeName;
    //}

    return component.base;
}

and the corresponding create function

create(ctor, props={}) {
  let list = componentRecycler.components[ctor.name];
  if (list && list.length) {
    for (let i=list.length; i--; ) {
      if (list[i].constructor===ctor) {
        return list.splice(i, 1)[0];
      }
    }
  }
  return new ctor(props);
}

It works fine, is that ok ?

Thanks :)

Implement context

Not sure if this is planned already but it seems like contexts are the main thing missing before getting parity with React.

This will mean adding lifecycle hooks for getChildContextand contextTypes as well as passing the context into the constructor, render(?) and shouldComponentUpdate.

unmountComponentAtNode

There seem to be no way to properly unmount components from domNode at the moment. Or maybe I am missing something?)
Any plans to add unmountComponentAtNode method?
Thanks =)

No need for @bind and ::this.method. We already have short function syntax.

I saw usage of @Bind and ::this.method in some examples.

I think it's better to change this to

class A extends Component {
    // With this syntax it will be already bound to this context
    handleSmthn = () => {
        this.setState({});
    }

    render() {
        return <div onClick={this.handleSmthn}>Clock me!</div>;
    }
}

It's much better and no need for additional tools.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.