Home > other >  Is it okay to create a Map to state values in React?
Is it okay to create a Map to state values in React?

Time:09-28

I'm wondering what the standard procedure is for mapping to values in the state in React. The map isn't part of the state it is just storing references to the state for easy access via keys, is there anything wrong with this?

Here's an example implementation

import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import Constants from 'expo-constants';
import {useEffect, useState} from 'react';


export default function App() {
  return (
    <View style={styles.container}>
      <Person personId={"Alice"} />
    </View>
  );
}

const Person = ({personId}) => {
  const [selector, setSelector] = useState(0);
  const [mom, setMom] = useState("");
  const [dad, setDad] = useState("");
  const parentMap = {
    0: mom,
    1: dad,
  };

  useEffect(() => {
    const fetchData = async () => {
      //pretend these are awaits involving personId which is 
      //why I can't pre-define the map values.
      const _mom = "Beth";
      const _dad = "Tim";

      setMom(_mom);
      setDad(_dad);
    };

    fetchData();
  }, []);

  return (
    <View style={{alignItems: "center"}} >
      <Text >
        Parents name: {parentMap[selector]} 
      </Text>
      <Button title="Toggle selector" onPress={() => setSelector(s => (s   1) % 2)} />
    </View>
  );
}

CodePudding user response:

Nothing wrong with it. You can derive the state to get whatever you need. If it's computationally expensive, you could memoize with useMemo, but it's rarely necessary.

The rule of thumb is to keep your local state as normalised as possible. You can then combine/aggregate/transform it as you see fit.

const [a, setA] = useState(0);
const [b, setB] = useState(0);

const hypotenuse = Math.hypot(a, b) // don't put this in the state, derive it instead

CodePudding user response:

There's nothing inherently wrong with it, though IMO it's a bit of a code smell due to the duplication. In a situation like this, you might consider making the object the state, instead of having separate states for both mom and dad - the object will also make it easier to extend the component to add additional values later (like child and grandparent, etc).

You also might consider using an array instead of an object, since it looks like the keys will always be numeric indicies starting from 0.

const Person = ({ personId }) => {
    const [selectedIndex, setSelectedIndex] = useState(0);
    const [values, setValues] = useState(['', '']);
    useEffect(() => {
        setValues([_mom, _dad]);
    }, []);
    return (
        <View style={{ alignItems: "center" }} >
            <Text >
                Parents name: {values[selectedIndex]}
            </Text>
            <Button title="Toggle selector" onPress={() => setSelectedIndex(s => (s   1) % values.length)} />
        </View>
    );
};

CodePudding user response:

What you wrote isn't wrong, but it's not a common approach.

An improvement would be something similar to the below.

const Person = ({personId}) => {
  const [mom, setMom] = useState("");
  const [dad, setDad] = useState("");
  const [isMomVisible, setIsMomVisible] = useState(true);


  useEffect(() => {
    const fetchData = async () => {
      const _mom = "Beth";
      const _dad = "Tim";

      setMom(_mom);
      setDad(_dad);
    };

    fetchData();
  }, []);

  return (
    <View style={{alignItems: "center"}} >
      <Text >
        Parents name: {isMomVisible ? mom : dad} 
      </Text>
      <Button title="Toggle selector" onPress={() => setIsMomVisible(s => (!s))} />
    </View>
  );
}

Here's a working expo

  • Related