티스토리 뷰
반응형

오류

Flutter로 사이드 프로젝트를 진행하며 기존의 버튼 위젯에 Provider 패턴을 적용해 보고 있었다.

ChangeNotifier을 Mixin하고 ChangeNotifierProvider을 이용하여 데이터를 생성, 사용 할 Container를 감싸주었다.

 

그 다음, ChangeNotifierProvider의 child에서 Provider.of(context)와 같은 형식으로 전달받은 데이터를 이용하려 하였는데, 다음과 같은 오류가 발생했다.

 

 

Error: Could not find the correct Provider above this HomeScreen Widget

 

 

원인

위 오류의 원인은 디버그 콘솔에 나타난 오류 메세지에서 쉽게 찾을 수 있었다.

먼저, 코드를 보면서 어떤식으로 Provider가 사용되었는지 살펴보자. 아래의 코드는 설명을 위해 만들어본 예시코드이다.

 

예시코드

 

 

코드를 간단히 설명해 보자면 아래와 같다.

  1. HomeScreen 위젯에서 ChangeNotifierPorivder을 사용하였고, ButtonModel을 데이터로 사용한다.
  2. provider의 child는 Column이고, Colum안에는 1개의 Container(100x100), 2개의 버튼이 존재한다.
  3. Column안의 요소들은 각각 Provider.of(context)와 같은 형식으로 데이터에 접근하려한다.
  4. 데이터 접근을 통해, 각 버튼이 클릭될 때 마다 Container의 색을 바꾸도록 작성된 코드이다.

 

오류 메세지 확인

이번에는 위의 코드에서 잘못된 부분을 찾기 위해 디버그 콘솔을 한 번 살펴보자.

 


❗ **Error: Could not find the correct Provider above this HomeScreen Widget**

This happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:

You added a new provider in your main.dart and performed a hot-reload.
To fix, perform a hot-restart.
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that HomeScreen is under your MultiProvider

/Provider

.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // Will throw a ProviderNotFoundError, because `context` is associated
      // to the widget that is the parent of `Provider<Example>`
      child: Text(context.watch<Example>().toString()),
    );
  }

consider using builder like so:

  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // we use `builder` to obtain a new `BuildContext` that has access to the provider
      builder: (context, child) {
        // No longer throws
        return Text(context.watch<Example>().toString());
      }
    );
  }
  
If none of these solutions work, consider asking for help on StackOverflow:

https://stackoverflow.com/questions/tagged/flutter

 

먼저, 오류 메세지 2번째 줄을 살펴보자.

This happens because you used a BuildContext that does not include the provider of your choice.
: 당신이 선택한 Provider을 포함하고 있지 않은 BuildContext를 사용했기 때문에 이 오류가 발생하였습니다.

라는 문장을 볼 수 있다. 또한, 그 밑에는 몇 가지의 오류가 발생했을 법한 경우가 나열되어있는데, 그 중 나에게 해당되는 것은 가장 마지막 시나리오였다.

 

 

You used a BuildContext that is an ancestor of the provider you are trying to read.

즉, 내가 Provider를 사용하며 넘겨준 context는 HomeScreen위젯 최상단의 Buildcontext이기 때문에 이 오류가 발생한 것이다.

 

 

정리하자면, 나는 HomeScreen위젯의 하위에 ChangeNotifierProvider을 작성하였음에도, 데이터를 사용할 때에는 Provider.of<>(context) 명령어로 HomeScreen의 context를 넘겨주었으니 해당 context에는 ChangeNotifierProvider에 관한 정보가 존재하지 않는 것이다.

 

해결법

해결방법은 디버그 콘솔의 예시를 따라하니 간단히 해결되었다.

그 방법은 바로 builder을 이용하는 것이다.

This usually happens when you are creating a provider and trying to read it immediately.
  For example, instead of:
  
  Widget build(BuildContext context) {
	return Provider(
		create: (_) => Example(),
		// Will throw a ProviderNotFoundError, because context is associated
		// to the widget that is the parent of Provider<Example>
    	child: Text(context.watch().toString()),
	);
}
consider using `builder` like so:
Widget build(BuildContext context) {
	return Provider(
		create: (_) => Example(),
		// we use builder to obtain a new BuildContext that has access to the provider
		builder: (context, child) {
			// No longer throws
			return Text(context.watch().toString());
		}
	);
}

 

이처럼 데이터 생성을 위해 Provider을 작성할 때, child가 아닌 builder을 사용하여 Provider의 정보가 포함된 context를 인자로 넘겨주면 문제를 해결 할 수 있다. 수정된 코드는 아래와 같다.

 

수정된 코드.&nbsp;ChangeNotifierProvider의 child를 builder로 변경 한 후, context를 넘겨주었다.

이처럼, builder를 사용하여 Provider의 정보가 포함된 BuildContext를 새로 넘겨주어 문제를 해결 할 수 있었다.

 

느낀점

기존에 Global key를 이용하여 비효율적으로 작성했던 코드를 개선하기 위해 Provider을 처음으로 사용해보았다.

그러나 Provider의 사용 예시를 따라하는데 너무 급급한 나머지 가장 기본적인 BuildContext를 고려하지 않아 이런 오류를 발생시킨 것 같다.

 

단순히 작동하는 코드를 짜는 것보다, 구조를 이해하고 코드를 작성하도록 노력해야겠다.

그리고 바로 검색하는 것 보다는 공식문서나 내부 코드를 찾아보는게 많은 도움이 될 것 같다.

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함