Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning a new Dart 3 type Record from the useState hook #366

Open
jezsung opened this issue Jul 6, 2023 · 7 comments
Open

Returning a new Dart 3 type Record from the useState hook #366

jezsung opened this issue Jul 6, 2023 · 7 comments
Assignees
Labels
breaking enhancement New feature or request

Comments

@jezsung
Copy link
Contributor

jezsung commented Jul 6, 2023

This library currently returns a ValueNotifier which is a wrapper class for the value of the useState.

With class destructuring, we can destructure a ValueNotifier like the below:

var ValueNotifier(:value) = useState<String>('Hello World!');

In this approach, it's impossible to give another variable name for the value which is not flexible.

Dart 3 has introduced a new feature called Pattern with array destructuring.

Basically, we can write code like the following:

var numList = [1, 2, 3];
var [a, b, c] = numList;

I propose to change the return value to an array and return the value and the function that can modify the value.

final [state, setState] = useState('Hello World!');

In this way, we can declare the state as a final variable and make a change by calling the setState function.

@rrousselGit
Copy link
Owner

In this approach, it's impossible to give another variable name for the value which is not flexible.

That isn't true.
You can do:

var ValueNotifier(value: myName) = useState(..);

But to begin with, you probably wouldn't use destructuring for useState with ValueNotifier.

We could change useState to return a tuple (not a list though). But that would be quite breaking.

@jezsung
Copy link
Contributor Author

jezsung commented Jul 6, 2023

@rrousselGit

Thanks for correcting me. I didn't know that I can give a custom name when destructuring class.

I realized returning a List isn't type-safe. So I made a custom hook that returns a Record:

typedef Updater<T> = T Function(T previousData);

typedef SetState<T> = void Function(Updater<T> updater);

(T, SetState<T>) useDart3State<T>(T initialData) {
  final valueNotifier = useState<T>(initialData);

  setState(Updater<T> updater) {
    valueNotifier.value = updater(valueNotifier.value);
  }

  return (valueNotifier.value, setState);
}

I can be used like this:

final (text, setText) = useDart3State<String>('Hello World');

It does exactly what I described, but implementing this to the useState hook would be a quite breaking change. I wonder if this is worth it.

@jezsung
Copy link
Contributor Author

jezsung commented Jul 7, 2023

I found this syntax is just a new way of declaring variables and it doesn't really call the underlying setter of the ValueNotifier.

var ValueNotifier(:value) = useState(0);

// Does not actually increment. 
value++;

I believe added advantage of returning a Record over a ValueNotifier would be:

• Separated way of reading and updating the value
• Succinct one-line variable declaration
• More React-like syntax

I think this change is worth it. This would affect a huge codebase for developers but considering that it's just a minor syntax change, there wouldn't be much headache while migrating to this new syntax. Also, this would attract more developers who have a React background. What do you think? @rrousselGit

@jezsung jezsung changed the title Can we use the Dart 3 Pattern to return an array from the useState hook? Returning a new Dart 3 type Record from the useState hook Jul 7, 2023
@rrousselGit
Copy link
Owner

I found this syntax is just a new way of declaring variables and it doesn't really call the underlying setter of the ValueNotifier.

var ValueNotifier(:value) = useState(0);

There's no reason to use destructuring though.

You'd write:

final myState = useState(0);
myState.value++;

@rrousselGit
Copy link
Owner

Making this change is heavily breaking. The only value is being closer to react, and wining a tiny bit of memory. I'm not sure that's worth it.

@bruce3x
Copy link

bruce3x commented Aug 31, 2023

Maybe provide a new API?

final [count, setCount] = useStateValue(123);

@listepo
Copy link

listepo commented Dec 20, 2023

Nice idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants