Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Function can't read useState parameters

I’m building an app with React Native and Firebase Realtime Database, when I start the function addItem the only parameter in the object that I get from the Database is the id, the other paramters return as '', I’ve tried using console.log() and the TextInputs work fine also I’ve used this configuration a lot of times and this is the first time it happens.

export default function NewItem() {

    const [name, setName] = useState('');
    const [price, setPrice] = useState('');
    const [description, setDescription] = useState('');

    useEffect(() => {
        navigation.setOptions({
            headerRight: () => (
                <TouchableOpacity onPress={addItem}>
                    <Text style={{fontWeight:'bold'}}>ADD ITEM</Text>
                </TouchableOpacity>
            )
        })
    }, [])

    const addItem = () => {

        const changes = ref(db, 'path')
        get(changes).then( async (snapshot) => {
            if (snapshot.val().data !== undefined) {

                let array = []

                let object = {
                    "id": `${id}`,
                    "name": name,
                    "price": price,
                    "description": description,
                }

                array.push(object)
                
                update(changes, {
                    data: array
                })

            }
        })
    }

  return (
    <TouchableWithoutFeedback>
            <TextInput
                onChangeText={(e) => setName(e)}
            />
            <TextInput
                onChangeText={(e) => setShippingPrice(e)}
                    />
            <TextInput
                onChangeText={(e) => setPrice(e)}
            />
            <TextInput
                onChangeText={(e) => setDescription(e)}
            />
    </TouchableWithoutFeedback>
  )
}

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

addItem is a stale enclosure over the state it references since the useEffect hook runs only once and closes over the initial state. You can likely resolve by re-enclosing the updated state by adding addItem function to the dependency array.

useEffect(() => {
  navigation.setOptions({
    headerRight: () => (
      <TouchableOpacity onPress={addItem}>
        <Text style={{fontWeight:'bold'}}>ADD ITEM</Text>
      </TouchableOpacity>
    )
  })
}, [addItem]);

You should memoize the addItem callback handler to further reduce the number of times the useEffect hook above re-encloses the callback/state.

const addItem = React.useCallback(() => {
  const changes = ref(db, 'path');
  get(changes)
    .then(async (snapshot) => {
      if (snapshot.val().data !== undefined) {
        const data = [{
          "id": `${id}`,
          name,
          price,
          description,
        }];
                
        update(changes, { data });
      }
    })
}, [name, price, description]);

Alternatively you could cache all the state values in a React ref and access them via the ref in the callback.

Example:

export default function NewItem() {
  const [name, setName] = useState('');
  const [price, setPrice] = useState('');
  const [description, setDescription] = useState('');

  const stateRef = React.useRef({
    name,
    price,
    description,
  });

  useEffect(() => {
    stateRef.current = { name, price, description };
  }, [name, price, description]);

  useEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <TouchableOpacity onPress={addItem}>
          <Text style={{fontWeight:'bold'}}>ADD ITEM</Text>
        </TouchableOpacity>
      )
    })
  }, []);

  const addItem = () => {
    const changes = ref(db, 'path');
    get(changes)
      .then(async (snapshot) => {
        if (snapshot.val().data !== undefined) {
          const { name, price, description } = stateRef.current;
          const data = [{
            "id": `${id}`,
            name,
            price,
            description,
          }];
                
          update(changes, { data });
        }
      })
  }

  return (...);
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading