Giter Site home page Giter Site logo

fre's Introduction

fre logo

Fre

👻 Tiny React16 like library with Concurrent and Suspense.

Build Status Code Coverage npm-v npm-d gzip prettier

Feature

  • 🎉 Functional Component and hooks API
  • 🎊 Concurrent and Suspense
  • 🔭 keyed reconcilation algorithm

Contributors

Fre has wonderful code, we need more to join us and improve together.

Backers

Thanks for the following websites and sponsors, If you do the same, please tell us with issue~

Real world

clicli.me

Any other demos click here

Use

yarn add fre
import { h, render, useState } from 'fre'

function App() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

render(<App />, document.getElementById('root'))

Hooks API

useState

useState is a base API, It will receive initial state and return a Array

You can use it many times, new state is available when component is rerender

function App() {
  const [up, setUp] = useState(0)
  const [down, setDown] = useState(0)
  return (
    <div>
      <h1>{up}</h1>
      <button onClick={() => setUp(up + 1)}>+</button>
      <h1>{down}</h1>
      <button onClick={() => setDown(down - 1)}>-</button>
    </div>
  )
}

useReducer

useReducer and useState are almost the same,but useReducer needs a global reducer

function reducer(state, action) {
  switch (action.type) {
    case 'up':
      return { count: state.count + 1 }
    case 'down':
      return { count: state.count - 1 }
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, { count: 1 })
  return (
    <div>
      {state.count}
      <button onClick={() => dispatch({ type: 'up' })}>+</button>
      <button onClick={() => dispatch({ type: 'down' })}>+</button>
    </div>
  )
}

useEffect

It is the execution and cleanup of effects, which is represented by the second parameter

useEffect(f)       //  effect (and clean-up) every time
useEffect(f, [])   //  effect (and clean-up) only once in a component's life
useEffect(f, [x])  //  effect (and clean-up) when property x changes in a component's life
function App({ flag }) {
  const [count, setCount] = useState(0)
  useEffect(() => {
    document.title = 'count is ' + count
  }, [flag])
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

If it return a function, the function can do cleanups:

useEffect(() => {
    document.title = 'count is ' + count
    reutn () => {
      store.unsubscribe()
    }
}, [])

useLayout

More like useEffect, but useEffect queue in requestAnimationFrame, but useLayout is sync and block commitWork.

useLayout(() => {
  document.title = 'count is ' + count
}, [flag])

useMemo

useMemo has the same parameters as useEffect, but useMemo will return a cached value.

function App() {
  const [count, setCount] = useState(0)
  const val = useMemo(() => {
    return new Date()
  }, [count])
  return (
    <div>
      <h1>
        {count} - {val}
      </h1>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

useCallback

useCallback is based useMemo, it will return a cached function.

const cb = useCallback(() => {
  console.log('cb was cached')
}, [])

The implement amount to

useMemo(() => cb, deps)

useRef

useRef will return a function or an object.

function App() {
  useEffect(() => {
    console.log(t) // { current:<div>t</div> }
  })
  const t = useRef(null)
  return <div ref={t}>t</div>
}

If it use a function, It can return a cleanup and exectes when removed.

function App() {
  const t = useRef(dom => {
    if (dom) {
      doSomething()
    } else {
      cleanUp()
    }
  })
  return flag && <span ref={t}>I will removed</span>
}

Awesome API

There are some awesome APIs, It used outside of component, Usually a with prefix is used.

withContext

Simplify context implement for hooks, no need Provider or useContext, share state easier.

const useTheme = withContext('light')

function App() {
  const [theme, setTheme] = useTheme()
  return (
    <div>
      {theme}
      <A />
      <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
        change
      </button>
    </div>
  )
}

function A() {
  const [theme] = useTheme()
  return <div>{theme}</div>
}

withSuspense

One API to suspense not only fetch data but also dynamic component.

const useUser = withSuspense(pageSize =>
  fetch(`https://api.clicli.us/users?level=4&page=1&pageSize=${pageSize}`)
    .then(res => res.json())
    .then(next => next.users)
)
const OtherComponent = withSuspense(() => import('./other-component'))

function App() {
  const users = useUser(pageSize)
  return <OtherComponent users={users} />
}

render props / children

const HelloBox = () => <Box render={value => <h1>{value}</h1>} />

const Box = props => <div>{props.render('hello world!')}</div>
const HelloBox = () => (
  <Box>
    {value => {
      return <h1>{value}</h1>
    }}
  </Box>
)

const Box = props => <div>{props.children('hello world!')}</div>

Concurrent

Fre implements a tiny priority scheduler, which called Concurrent Mode.

It uses the linked list data struct to iterate a tree, which can better break, continue, and fallback.

At the same time, it uses double buffering to separate reading and writing.

Of course, the new data struct brings different algorithms and many possibilities.

time slicing

Time slicing is the scheduling of reconcilation, synchronous tasks, sacrifice CPU and reduce blocking time

Suspense

Suspense is the scheduling of promise, asynchronous tasks, break current tasks, and continue tasks after promise resolve

key-based reconcilation

Fre implements a compact reconcilation algorithm support keyed, which also called diff.

It uses hash to mark locations to reduce much size.

License

MIT ©yisar inspired by react anu

fre's People

Contributors

yisar avatar mindplay-dk avatar wu-yu-xuan avatar malash avatar yiliang114 avatar zhenhe17 avatar iosh avatar ashmit4 avatar dependabot[bot] avatar duhongjun avatar

Watchers

James Cloos avatar

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.