Flutter Hooks: https://github.com/rrousselGit/flutter_hooks

Flutter Hooks는 React의 Hooks와 이를 분석한 미디엄 글을 보고 영감을 받아 flutter에 맞도록 hook 을 구현한 패키지이다. StatefulStateless 를 구분할 필요 없이 하나의 HookWidget으로 모든 위젯을 표현할 수 있도록 도와주며, 위젯 lifecycle 및 로컬 state 관리와 관련하여 다양한 편의성을 제공한다.

본 글에서는 간단하게 flutter_hooks 패키지를 사용하는 법을 살펴보도록 한다.

설치하기

패키지 설치는 여타 다른 패키지나 플러그인 설치와 동일하다. 실제 앱의 위젯을 구성하는데 사용될 위젯 패키지 이므로 pubspec.yamldependencies 섹션에 추가하면 된다.

# pubspec.yaml 파일
dependencies:
	flutter_hooks: any

이후 다른 패키지 설치와 동일하게 flutter pub get 을 수행하면 된다.

예제

간단한 샘플 앱 2개를 보면서 사용법을 알아보자. 아래는 AnimationController 의 사용이 필요한 StatefulWidget 을 다루는 예제이다.

Animation

class AnimationWidget extends StatefulWidget {
	const AnimationWidget({Key key, @required this.duration}) : super(key:key);
	final Duration duration;
	
	@overrider
	_AnimationWidgetState createState() => _AnimationWidgetState();
}
class _AnimationWidgetState extends State<Example> with SingleTickerProviderStateMixin {
	AnimationController _controller;

	@override
	void initState() {
		super.initState();
		// 로직과 상관없는 코드 #1 - 컨트롤러 초기화
		_controller = AnimationController(vsync: this, duration: widget.duration);
	}

	@override 
	void didUpateWidget(Example oldWidget) {
		super.didUpdateWidget(oldWidget);
		if (widget.duration != oldWidget.duration) {
			_controller.duration = widget.duration; // 로직과 상관없는 코드 #2 - 업데이트
		}
	}
	
	@override
	void dispose() {
		_controller.dispose(); // 로직과 상관없는 코드 #3 - 컨트롤러 해제
	}

	@override
	Widget build(BuildContext context) {
		return Container();
	}
}

StatefulWidget 과 그에 따른 state를 정의하기 위한 State 클래스, 그리고 애니메이션 사용을 위한 mixin 추가를 위한 with 까지, 클래스 생성부터 부가적인 코드가 너무 많이 들어있는 것을 볼 수 있다. 또한 AnimationController 의 안전한 할당/해제를 위한 lifecycle 메소드까지 들어가서, 실제 UI나 로직을 위한 코드가 들어가는 build 메소드 외에 수십줄이 추가됨을 알 수 있다.

flutter_hooks 는 이러한 부가적인 코드를 대신하여 실제 플러터 개발자는 온전히 UI와 로직에만 신경쓸 수 있도록 도와주는 위젯 패키지 이다. 기본적으로 Stateful이나 Stateless 위젯 대신 HookWidget 을 상속하여 원하는 위젯을 개발하면 되고, 기타 state 관리나 생명주기 관리 등은 같이 제공 되는 기본 Hooks 를 사용하거나, Hooks 를 커스텀하여 사용할 수 있다.

flutter_hooks 적용하기

위의 코드를 flutter_hooks 를 이용해 간소화 시킨 코드는 아래와 같다.

import 'package:flutter_hooks/flutter_hooks.dart';
class AnimationWidget extends HookWidget {
	const AnimationWidget({Key key, @required this.duration}):super(key:key);
	
	@override
	Widget build(BuildContext context) {
		final controller = useAnimationController(duration:duration);
		return Container(
			/* controller를 사용하는 코드 추가 */
		);
	}
}

거의 1/3 수준으로 줄어든 코드량을 볼 수 있다. 이는 flutter_hooks가 미리 정의한 useAnimationController 가 필요한 작업을 모두 대신해주기 때문이다. 본 글은 소개를 위한 글이므로 구현에 대한 자세한 설명은 생략한다.

데이터 변화에 따른 위젯 업데이트

플러터 기본 예제인 카운터를 비롯하여 다양한 위젯에서 데이터 변경에 따라 위젯을 업데이트 하고 싶은 경우 StatefulWidgetsetState를 사용한다. 그러나 이러한 코드는 위의 애니메이션 예제에서 보여줬듯이 부수적인 코딩을 요구한다. flutter_hooks를 사용하면 이 또한 간단하게 줄일 수 있다.