Yes, you have your variable defined, but it is not visible in the place where you want to use it.
In your first snippet:
if (productId != null) { final loadedProduct = Provider.of<Products>(context) .items .firstWhere((prod) => prod.id == productId); } return Scaffold( appBar: AppBar( title: Text(loadedProduct.title), ), );You created loadedProduct but it is only accessible within {} brackets of your if statement. It is called Lexical Scoping.
In your second snippets, you can see that you try to use loadedProduct variable in a proper scope - it doesn't return undefined. Though notice that if productId is null and its if block doesn't execute - you tells your widget to build nothing - null, which is not possible. Consider a simple else clause to handle it.
if (productId != null) { final loadedProduct = Provider.of<Products>(context) .items .firstWhere((prod) => prod.id == productId); return Scaffold( appBar: AppBar( title: Text(loadedProduct.title), ), ); } else { return Container() }