dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.11k stars 1.73k forks source link

[Enhancement] Copy react native JSX programming style. #286

Closed Jonatthu closed 3 years ago

Jonatthu commented 3 years ago

This would require a new syntax for vscode and a new transpiler BUT it is worth it!

I imagine c# component classes with dependency injection and a method called render and jsx like XML but using c# and dotnet 5/6!

It would be really nice

GeraudFabien commented 3 years ago

Why would it be "really nice" to someone that never done React native before. What the goal? How? Can you explain what is you're current problem?

Seems like you are used to react native. And ask "Can you transform everything's else in react native this way i can do any thinks without learning?". But most of the people are not used to React native. Or don't thinks it's a great. What about them?

Jonatthu commented 3 years ago

The first platform to success in cross-platform development in terms of usage, number of contributions and community is react native, they are doing something great, c# is my preferred language and as I said, by copying the programming style language of JSX would not break the "regular" programming style designed for maui sr. @GeraudFabien It would be an "optional" feature that I think would be really good to migrate a lot of developers coming from react native to maui. EVEN microsoft develops with react native so I THINK this would be KEY feature to BRING community like me.

:D

GeraudFabien commented 3 years ago

Sorry i thinks there is a misunderstanding. I'm not against or poor the idea I just want to know why and how. If you could get a sample on what you want. Or a big key feature (dependency injection and a method called XXX that render is not really new to C#, so i assume jsx like XML). But i assume if you say "Like" it means you don't ask for exactly the same...

The first platform to success in cross-platform development in terms of usage, number of contributions and community is react native

This doesn't mean everyone like it. And most develop in other tool. I barely tryed it so i just want to understand what's you want (Native, Bindind, css like styling).

redradist commented 3 years ago

This would require a new syntax for vscode and a new transpiler BUT it is worth it!

I imagine c# component classes with dependency injection and a method called render and jsx like XML but using c# and dotnet 5/6!

It would be really nice

@Jonatthu It is not worth it ... Look at Blazor mobile binding, it is already jsx like approach but better because you do not have such mixing of code and markup

Jonatthu commented 3 years ago

@redradist It is not about what it is "better", since many BIG companies including microsoft did not doubt in jump into react native (: It is about that I like c# and would like to see my react native apps on c#... I have many in app store and I can tell that I love react native but not too much javascript :) I rather prefer c#, and I know many people on the community that prefers c# as well. Anyways even without this feature ONLY time would tell what's better or not. Sometimes is about community and speed to deliver something...

GeraudFabien commented 3 years ago

It is not about what it is "better"

Yes that why i ask for the goal/Problem/Case this issue want to solve. If the goal is Help web developper use xamarin or fill the gap between Xamarin and blazor to have just the UI part diffrents but with the same code look and feel (XML/Binding style/CSS CF. Mobile blazor binding).

BIG companies including microsoft did not doubt in jump into react native (:

Big company use evrythinks. as they are big they have small, medium and big project and most doesn't want to depend on one technology only. React native isn't new or old (5 year) and i don't feel like there i a lot of people using it. there is not a lot of developer or project.

@Jonatthu Again if you don't give a sample or a lengthly explaination about what you want we can't know what you are asking for. What part do you want to "Copy" is it a feature? If you want full ract native with C# backend it's a totally different project. It may be possible to do some thinks with WASM (1, 2, 3). But this has nothinks to do with maui.

alfosua commented 3 years ago

I think that the upcoming MVU-pattern could offer some basis in the way how we can achieve this, or at least, for functional-based development with React. Instead of explicitly copying JSX, we can do somewhat like a CXX (Csharp Xaml eXpressión, I'm open to any other name). It may decrease the learning curve, not just for React/React Native developers, but pretty much any new one. It admit that I found React plus JSX as an easy-to-learn pattern.

Let me refactor the MVU example from this post to look at how it could seem. First, this example is more based on JSX patterns:

private readonly State<int> count = 0;

Component Render() =>
    <StackLayout>
        <Label>Welcome to .NET MAUI!</Label>
        <Button OnPress={ () => count.Value++ }>
            You clicked { count } times.
        </Button>
    </StackLayout>

This might be more according with XAML syntax:

private readonly State<int> count = 0;

Component Render() =>
    <StackLayout>
        <Label Text="Welcome to .NET MAUI!" />
        <Button Text="You clicked { count } times."
                      Command={ () => count.Value++ } />
    </StackLayout>

Notice I did not use string interpolation in the Label's property Text="You clicked { count } times.", because it should not be necessary inside a CXX. Any curly-braces should mean a C# pure expression.

Also notice that this code is inside a normal C# file (with a .cs extension), and it is inside a typical class.

// I am the YouSolution/Components/Example.cs
using Microsoft.Maui;
using Microsoft.Maui.Cxx;

public class Example : Component
{
    private readonly State<int> count = 0;

    Component Render() =>
        <StackLayout>
            <Label Text="Welcome to .NET MAUI!" />
            <Button Text="You clicked { count } times."
                          Command={ () => count.Value++ } />
        </StackLayout>
}

The Component and State classes in this case comes from Microsoft.Maui.Cxx. And CXX code will only be available if using the Microsoft.Maui.Cxx namespace, or if the filename have the .cxx extension (which implicitly compiles with such using statement).

I will prefer to just adopt the Render implementation from the old React API for class-based components. Implementing the other stuff that the React.Component class does will seem redundant and unnecessary when having the powerfulness of hooks. Something that I'm sure C# can accomplish very well. I would rather prefer focusing on supporting functional-components over classy-components. Anyway, keeping both is wise.

Let me try to showcase some ideas that could fit with the C# syntax:

In YourSolution/Components/CustomButton.cxx:

[PropertyTypes(typeof(Button))]
public class CustomButton : Component
{
    // We can use public automatic properties to passing them through XAML 
    public Rect ContainerPadding { get; set; }

    public Component Render() =>
        <Container Padding={ ContainerPadding }>
            <Button Text={ Text } />
        </Container>
}

In YourSolution/Components/CustomLabel.cxx:

public class CustomLabel : Component
{
    public class PropertyTypes : Label.PropertyTypes
    {
        public Rect ContainerPadding { get; set; }

        public Builder<PropertyTypes> Configure(Builder<PropertyTypes> builder) =>
            builder.InheritsFrom<Label.PropertyTypes>()
                .And.Property(pt => pt.ContainerPadding)
                    .HasDefaultValue(new Rect(10));
    }

    public Component Render() =>
        <Container Padding={ ContainerPadding }>
            <Label Text={ Text } />
        </Container>
}

In YourSolution/Component/ComponentLibrary.cxx:

public static class ComponentLibrary
{
    // I may prefer to use PascalCase for functional component parameters (which are properties)
    public Component MyStatelessFunctionalComponent(int ValueA, int ValueB) =>
        <CustomLabel Text="{ ValueA } + { ValueB } = { ValueA + ValueB }" />

    // Component already implements the Children property
    public Component MyWrapperFunctionalComponent() =>
        <Container>
            { Children.Cast<Label>()
                .Select(x => <CustomLabel Text={ x.Text }/>) }
        </Container>

    public Component MyStatefulFunctionalComponent(int ValueA, int ValueB)
    {
        // I don't know if this is factible
        State<int> multiplier = 1;

        Action onIncrease = () => { multiplier.Value++ };
        Action onDecrease = () => { multiplier.Value-- };

        return (
            <MyWrapperFunctionalComponent>
                <Label Text="Current multiplier: { multiplier }" />
                <MyStatelessFunctionalComponent
                    ValueA={ 2 * multiplier } ValueB={ 4 * multiplier }
                 />
                <CustomButton Text="Increase multiplier" Command={ onIncrease } />
                <CustomButton Text="Decrease multiplier" Command={ onDecrease } />
            </MyWrapperFunctionalComponent>
        );
    }
}

And so, and so... Of course this would need of a great support from the compiler. But it is something that is possible.

Note: I may need to fix some identation. Sorry, the built-in Github text editor isn't so helpful for code...