Можно ли создать карту для указания значений в React?

#reactjs #react-native

Вопрос:

Мне интересно, какова стандартная процедура сопоставления со значениями в состоянии в React. Карта не является частью состояния, она просто хранит ссылки на состояние для легкого доступа с помощью ключей, в этом что-то не так?

Вот пример реализации

 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>
  );
}
 

Ответ №1:

В этом нет ничего изначально неправильного, хотя, ИМО, это немного пахнет кодом из-за дублирования. В подобной ситуации вы можете подумать о том, чтобы сделать объект состоянием, а не иметь отдельных состояний для обоих mom и dad — объект также облегчит расширение компонента для добавления дополнительных значений позже (например child , и и grandparent т. Д.).

Вы также можете рассмотреть возможность использования массива вместо объекта, так как похоже, что ключи всегда будут числовыми указателями, начинающимися с 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>
    );
};
 

Комментарии:

1. Что, если бы вместо просто мамы и папы у меня было 100 переменных?

2. Тогда использование вместо этого только массива или объекта сделало бы управление не несколько проще, а намного проще 🙂

Ответ №2:

В этом нет ничего плохого. Вы можете вывести состояние, чтобы получить все, что вам нужно. Если это дорого с точки зрения вычислений, вы могли бы useMemo запомнить , но это редко бывает необходимо.

Эмпирическое правило состоит в том, чтобы ваше местное состояние было как можно более нормализованным. Затем вы можете объединить/агрегировать/преобразовать его по своему усмотрению.

 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
 

Ответ №3:

То, что вы написали, не является неправильным, но это не распространенный подход.

Улучшением было бы нечто подобное приведенному ниже.

 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>
  );
}
 

Вот рабочая выставка