Giter Club home page Giter Club logo

froact's People

Contributors

fewkz avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

froact's Issues

Add simple way to connect to property changed events

Rather than having to do:

local height, setHeight = hooks.useState(0)
froact.TextLabel({
    Size = UDim2.new(1, 0, 0, height),
    Text = "Text",
    onChanged = function(rbx, property)
        if property == "TextBounds" then
            setHeight(rbx.TextBounds.Y)
        end
    end,
})

There should be a "bind" field that does the same:

local height, setHeight = hooks.useState(0)
froact.TextLabel({
    Size = UDim2.new(1, 0, 0, height),
    Text = "Text",
    bindTextBounds = setHeight,
})

In the background, this will create a callback for the Changed event.
Bind fields will only be generated for properties prefixed with Absolute, or TextBounds

Components that use children get their children set to nil after any rerenders

The faulty code is

froact/froact.lua

Lines 174 to 176 in c9790a0

local children = props[roact.Children]
props[roact.Children] = nil
return body(props, hooks, if children then children else blankChildren)

It sets the children to be blank after the first render, which is bad. We can fix this by removing the line that sets the props[roact.Children] to nil, but we don't really want children to be in props. Haven't quite figured out a better solution yet.
For now, to fix, you have to do this following code: local children = hooks.useMemo(function() return children end, {props}), since the children will get set correct whenever props change.

Change default children type to `{[string]: any}`

Right now, the children type is set to {any}, this means that froact is OK with you not giving each child in the children a string key. By changing this to {[string]: any} this would catch a lot of issues where you accidentally forget to write the name of the child you're going to make, which causes the children to be named with sequential numbers, which is super annoying to read in the explorer. However, having to write the name of every children sucks a lot and a lot of existing froact code would probably turn into a lot of errors without a clear reason why. This is semi-related to #9

Add new way to "name" things in froact

Currently, there is no way to "name" pure-function based components like you can for froact.c components. This encourages a semi-bad practice of making every component that could be a function into an actual component with it's extra overhead.
A way we could solve this is via a froact.name() function, that sets the "name" of the next element created by froact.

local function CoolButton(props: { text: string })
  froact.name("Cool Button") -- the next textbutton will be called "CoolButton" instead of "TextButton" in the explorer
  return froact.TextButton({
    Text = props.text,
  })
end

You would be able to use froact.name in lists, like so:

froact.list({}, {
  froact.name("Open Button")
  CoolButton({ text = "open" })
  froact.name("Close Button")
  CoolButton({ text = "close" })
})

if multiple names are set in a row, only the oldest name will apply until the name is consumed by creating a froact element, to allow the patterns such as above, where the name "Open Button" overwrites "Cool Button"

This would probably deprecate the key feature in the list's config. I think the key feature isn't very valuable, since it's not able to be derived from multiple props. By having froact.name() be a function, components could name themselves programmatically according to their props, such as froact.name(`Player-{props.userId}`)

This could potentially allow us to replace all children fields with a froact list, which would make writing code a lot simpler, since you won't have to name every single child, and won't run into the issue where children are named like "1", "2", "3", "4", etc, which is terrible for debugging in the explorer. Another solution to the 1 2 3 4 error is proposed here: #10

Templates should support returning cleanup methods in onUpdate

Currently when using templates you have to handle the cleanup function yourself in a verbose way:

local Button = froact.template({}, function(name, parent, onUpdate)
    local rbx = ReplicatedStorage.ButtonTemplate:Clone()
    rbx.Name = name
    rbx.Parent = parent
    local cleanup
    onUpdate(function(props)
        if cleanup then
            cleanup()
        end
        local conn = rbx.OnActivated:Connect(props.onActivated)
        cleanup = function()
            conn:Disconnect()
        end
    end)
    return function()
        if cleanup then
            cleanup()
        end
        rbx:Destroy()
    end
})

We should instead allow you to return a cleanup function in onUpdate, like so:

local Button = froact.template({}, function(name, parent, onUpdate)
    local rbx = ReplicatedStorage.ButtonTemplate:Clone()
    rbx.Name = name
    rbx.Parent = parent
    onUpdate(function(props)
        local conn = rbx.OnActivated:Connect(props.onActivated)
        return function()
            conn:Disconnect()
        end
    end)
    return function()
        rbx:Destroy()
    end
})

Make our own context

We should implement our own wrapper around context that would be fully typed.

api ideas:

froact.provide, makes the type for Context smaller, by not including Provider:

local context = froact.createContext({ hello = "world" }) -- infered type: Context<{ hello = "world" }>
local bah = froact.c({}, function(props, hooks)
    local value = hooks.useContext(context)
    return TextLabel({ text = `hello is {value.hello}` })
end
local element = froact.provide(context, { hello = "foo" }, {
    bah({})
})

similar to react

local context = froact.createContext({ hello = "world" } -- infered type: Context<{ hello = "world" }>
local bah = froact.c({}, function(props, hooks)
    local value = hooks.useContext(context)
    return TextLabel({ text = `hello is {value.hello}` })
end
local element = context.Provider({
    value = { hello = "foo" }
}, {
    bah({})
})

Context<T> should be { default: T, Provider: ({ value: T }) -> Element }, Consumer: any (too lazy to define consumer, you shouldn't use consumer, use the hook instead)

new way to do binding shiss

What do we want? Fully typed bindings! When do we want it? NOW!
Anyways, here's what it would look like:

image

Beautiful, right? Absolutely glorious and game-changing.
Anyways, I figured out how to implement the types, so we'll be seeing it soon(er or later).
Instead of doing

local newBinding = Roact.joinBindings({binding1, binding2}):map(function(vals) 
    local v1, v2 = unpack(vals)
    return '' + v1 + ' ' + v2
end)

you get the luxury of being able to simply do:

local newBinding = froact.join(binding1, binding2).map(function(v1, v2)
    return '' + v1 + ' ' + v2
end)

Absolutely beautiful, if I do say so myself, and with full luau typing support! Everything is typed, which is not possible with the way Roact bindings are implemented.
image

Add ref types

Make a froact.createRef() function that returns { current: Instance }
with the code:

type Ref = { current: Instance }
local function createRef(): Ref
    return froact.Roact.createRef()
end

As it turns out, you can do .current on Roact refs. We can type the ref property on Roblox instance components as { current: Instance } so that you'll never fuck up the type of refs ever!

We get the beautiful, absolutely amazing extravagance of branch-based luau type inference! This is absolutely invaluable.
image

oh, and while we're add it, add froact.useRef(hooks), instead of doing hooks.useMemo(froact.createRef(), {})

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.