felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.79k stars 3.39k forks source link

bloc and hooks examples #168

Closed lsaudon closed 5 years ago

lsaudon commented 5 years ago

Describe the solution you'd like I would like to have an example to integrate flutter_hooks and flutter_bloc into flutter_todos or other.

felangel commented 5 years ago

Hi đź‘‹

What’s preventing you from using flutter_bloc with flutter_hooks? Are there any issues you’re running into?

lsaudon commented 5 years ago

I didn't have any problems. I'm blocked by my abilities. It was more of an example.

felangel commented 5 years ago

I’ll try to put something together over the next few days 👍

cyrsis commented 5 years ago

Great, Just found out my problem with Bloc can solve by Hook~ Let me give it a try

cyrsis commented 5 years ago

I did a study on hook, intended to solve my animation controller but end up move on with flare.

but I guess we are trying to solve same problem

let's take a look the map

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../Styles/AppStyleExport.dart';
import '../MapBlocExport.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class MapWidget extends StatefulWidget {
  MapWidget({Key key}) : super(key: key);

  @override
  _MapWidgetState createState() => new _MapWidgetState();
}

class _MapWidgetState extends State<MapWidget> {
  final Set<Marker> _markers = Set();
  final double _zoom = 15;
  CameraPosition _initialPosition =
      CameraPosition(target: LatLng(22.3527422, 114.1270739));
  MapType _defaultMapType = MapType.normal;
  GoogleMapController _controller;

  @override
  Widget build(BuildContext context) {
    return new BlocBuilder(
        bloc: BlocProvider.of<MapBloc>(context),
        builder: (context, state) {
          if (state is MapInitState) {
            return GoogleMap(
              markers: _markers,
              mapType: _defaultMapType,
              myLocationEnabled: true,
              onMapCreated: _onMapCreated,
              initialCameraPosition: _initialPosition,
              rotateGesturesEnabled: false,
              scrollGesturesEnabled: false,
              tiltGesturesEnabled: false,
            );
          }

          if (state is BetweenTwoBoundState) {
            _controller.animateCamera(
              CameraUpdate.newLatLngBounds(
                LatLngBounds(
                  southwest: LatLng(48.8589507, 2.2770205),
                  northeast: LatLng(50.8550625, 4.3053506),
                ),
                15.0, //Padding
              ),
            );
          }

          if (state is MoveNewCameraPositionState) {
            _controller.animateCamera(
              CameraUpdate.newCameraPosition(
                CameraPosition(
                  target: state.latLng,
                  tilt: 50.0,
                  //a higher tilt gives a side-view/tilted-view of buildings
                  bearing: 45.0,
                  //(the orientation of the map in degrees)
                  zoom: 20.0,
                ),
              ),
            );
          }

          if (state is GoToNewYorkState) {
            double lat = 40.7128;
            double long = -74.0060;
            double title = 50.0;
            double bearing = 45.0;

            _controller.animateCamera(CameraUpdate.newLatLngZoom(
              LatLng(lat, long),
              _zoom,
            ));
            _markers.clear();
            _markers.add(
              Marker(
                  markerId: MarkerId('newyork'),
                  position: LatLng(lat, long),
                  icon: BitmapDescriptor.fromAsset(
                    AppImage.payment_icoAddNew,
                  ),
                  infoWindow: InfoWindow(
                      title: 'New York', snippet: 'Welcome to New York')),
            );
          }

          if (state is ScrollByXyState) {
            _controller.animateCamera(
              CameraUpdate.scrollBy(50.0, 50.0),
            );
          }

          if (state is ChangeMapTypeState) {
            assert(state.mapType != null);
            return GoogleMap(
              markers: _markers,
              mapType: state.mapType,
              myLocationEnabled: true,
              onMapCreated: _onMapCreated,
              initialCameraPosition: _initialPosition,
            );
          }
          return GoogleMap(
            markers: _markers,
            mapType: _defaultMapType,
            myLocationEnabled: true,
            onMapCreated: _onMapCreated,
            initialCameraPosition: _initialPosition,
          );
        });
  }

  void _onMapCreated(GoogleMapController controller) {
    _controller = controller;
  }
}
felangel commented 5 years ago

@lsaudon sorry for the really long delay but I finally spent a bit of time and created a simple example using flutter_hooks with flutter_bloc which you can check out here.

I basically created a useBloc hook which handles creating and disposing the bloc for you so you don't need to create a StatefulWidget and initialize/dispose the bloc every time.

Hope that helps! đź‘Ť

rrousselGit commented 5 years ago

randomly passes here that useBloc is unnecessarily big.

useBloc could be:

T useBloc<T extends Bloc>(
    T Function() blocFactory,
    [List<Object> keys = const <dynamic>[]],
) {
  final bloc = useMemoized(blocFactory, keys);
  useEffect(() => bloc.dispose, [bloc]);
}

And you can make one for BlocBuilder too:

T useBlocListener<T>(Bloc<T, Object> bloc) {
  final state = useMemoized(() => bloc.state.skip(1), [bloc.state]);
  return useStream(state, initialData: bloc.currentState);
}
lsaudon commented 5 years ago

Do you have full exemple @rrousselGit ?

Chojecki commented 5 years ago

Would be awsome to see full example with usage @rrousselGit

cgestes commented 4 years ago

currently using the following sample in place of BlocProvider:

/*
 * use instead of BlocProvider<YoloBloc, YoloState>
 * state = useBlocState<YoloBloc, YoloState>();
 */
S useBlocState<B extends Bloc<dynamic, S>, S>() {
  final context = useContext();
  final bloc = BlocProvider.of<B>(context);

  final stream = useMemoized(() => bloc.skip(1), [bloc.state]);
  return useStream(stream, initialData: bloc.state).data;
}