flutterdartstatefulwidget

Passing data to a stateful widget


Why is this not working when I try to pass data from a TextEditingController in one screen to a Stateful widget in another screen?

Here is where I am passing the data in screen 1:

Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => DataScreen(zipController.text)));

Here is the code where I am trying to receive the data passed in the parameter in screen 2:

const String zipCode = '';

class DataScreen extends StatefulWidget {
  const DataScreen(this.zipCode, {super.key});  <<<  ERROR 1: this.zipCode  >>>
    
  @override
  _DataScreenState createState() => _DataScreenState();
}

class _DataScreenState extends State<DataScreen> {
  List<PropertyInformation> propertyList = [];

  bool isLoaded = false;

  Future<void> getItems() async {
    setState(() {
      isLoaded = true;
    });
    var client = http.Client();

    try {
      var url = Uri.parse(
          "https://realty-mole-property-api.p.rapidapi.com/properties?zipCode=$widget.zipCode");  <<<  ERROR 2  >>>
          
      final response = await client.get(
        url,
        headers: {
          'X-RapidAPI-Key': '51ced1b32emsh509f82e1d58ae16p1ad6e6jsn75d75166a8b4',
          'X-RapidAPI-Host': 'realty-mole-property-api.p.rapidapi.com'
        },
      );

      if (response.statusCode == 200) {
               var jsonData = jsonDecode(response.body);
    
        for (var element in jsonData) {
          element.removeWhere((key, value) => key == null || value == null);
        }        

        // decode the json
        for (var i in jsonData) {
          propertyList.add(PropertyInformation.fromJson(i));
        }

      } else {
        //print('Status Code: ${response.statusCode}');
      }
    } catch (e) {
      setState(() {
        isLoaded = false;
      });
      log("error $e");
    }

    setState(() {
      isLoaded = false;
    });
  }

  @override
  void initState() {
    getItems();
    super.initState();
  }

The first error I get is on "this.zipCode" and the error message is "'zipCode' isn't a field in the enclosing class." I have tried to look it up but I don't get results.

The second error is where I try to use the zipCode value ($widget.zipCode). I don't really know if it is an error but the word "widget" is white and .zipCode is the same text color as the rest of the URL string. When I hover over "widget" this message is displayed: "The current configuration. A [State] object's configuration is the corresponding [StatefulWidget] instance. This property is initialized by the framework before calling [initState]. If the parent updates this location in the tree to a new widget with the same [runtimeType] and [Widget.key] as the current configuration, the framework will update this property to refer to the new widget and then call [didUpdateWidget], passing the old configuration as an argument."

I have been following some examples I found on the internet but I can't figure out why I am getting the errors.

Please correct me.


Solution

  • first: Error with this.zipCode: The error message "'zipCode' isn't a field in the enclosing class" indicates that the zipCode parameter is not recognized in your constructor. The issue here is that you have defined zipCode as a parameter in the constructor, but you haven't actually declared it as an instance variable in the class. To fix this, you should declare zipCode as an instance variable in the DataScreen class.

        class DataScreen extends StatefulWidget {
          final String zipCode; // Declare the instance variable here
        
          const DataScreen(this.zipCode, {Key? key}) : super(key: key);
            
          @override
          _DataScreenState createState() => _DataScreenState();
        }
    

    Second: Usage of widget.zipCode: You're using $widget.zipCode to access the zipCode parameter passed to the DataScreen widget. However, in Flutter, the correct way to access this parameter within a State class is simply widget.zipCode. You don't need the $ symbol. Also, the IDE might show widget in white or gray color, but that's not an issue; it's just a coloration style.

    So, your URL construction should look like this:

        var url = Uri.parse(
            "https://realty-mole-property-api.p.rapidapi.com/properties?zipCode=${widget.zipCode}");
    
    

    With these changes, your code should work Perfectly.