есть ли способ запомнить функцию, которая возвращает случайный цвет на каждой итерации в реакции - PullRequest
0 голосов
/ 19 июня 2020

Я создаю собственное приложение для контактов, которое генерирует случайный цвет для каждого номера контакта. Я хочу запоминать возвращаемое значение функции генератора случайных цветов на каждой итерации, поэтому, когда я ищу контакты, цвет не будет меняться при каждом действии.

в настоящее время я использую useMemo реакции для запоминания результат функции, но я получаю недействительный хук, потому что я не могу использовать хуки внутри нормальной функции с al oop.

Поскольку мой код ниже, ловушка useMemo вызывается только при первом рендеринге или когда компонент перерисовывает. Я могу вернуть только одно значение, потому что я не могу использовать useMemo внутри карты.

вот мой код ⬇. Спасибо за помощь

const Contacts = () => {
  const [contact, setContact] = useState({});

  const randomColor = useMemo(() => randomColorGenerator(), []);


  useEffect(() => {}, []);

  const renderContacts = item => {
      return item.phoneNumbers.map(element => (
        <TouchableOpacity
          activeOpacity={1}
          key={element.digits.toString()}
          }}
        >
          <View>
                <View>
                  <Text>{item.firstName}</Text>
                  <Text>{element.digits}</Text>
                </View>
          </View>
        </TouchableOpacity>
      ));
  };

  const renderList = () => {
    return (
      <FlatList
        keyboardShouldPersistTaps="handled"
        data={contact}
        keyExtractor={(item, index) => index.toString()}
        renderItem={({ item }) => {
          return <View>{renderContacts(item)}</View>;
        }}
      />
    );
  };

  return (
    <View>
      <Text style={Styles.textStyle}>All Contacts</Text>
      {renderList()}
    </View>
  );
};

Ответы [ 3 ]

0 голосов
/ 20 июня 2020

Я бы просто предложил создать вашу собственную чистую javascript оболочку вокруг randomColorGenerator, которая кэширует значения на основе ключа для получения согласованного результата. Что-то вроде:

const memoizedRandomColorGenerator = function() {
  const cache = {};
  return function(k) {
    if (typeof cache[k] !== 'undefined') {
      return cache[k];
    }
    cache[k] = randomColorGenerator();
    return cache[k];
  }
}() // note that we are immediately invoking this function to close over the cache

Определите это где-то вне вашего компонента, чтобы он создавался только один раз. Затем используйте его в компоненте

  const renderContacts = item => {
      return item.phoneNumbers.map(element => (
        <TouchableOpacity
          activeOpacity={1}
          key={element.digits.toString()}
          }}
        >
          <View style={{
            backgroundColor: memoizedRandomColorGenerator(element.digits.toString())
          }}>
                <View>
                  <Text>{item.firstName}</Text>
                  <Text>{element.digits}</Text>
                </View>
          </View>
        </TouchableOpacity>
      ));
  };
0 голосов
/ 20 июня 2020

Цвет может быть любым свойством контакта, которое можно установить ранее и сохранить внутри контакта.

Или цвет может быть функцией ${contact.firstName} ${contact.lastName}. Вы можете получить шестнадцатеричное значение ha sh из строки, затем цвет из ha sh.

Таким образом, вы получите постоянное назначение между контактами и цветами.

useMemo предназначен для тяжелых вычисления, которые возвращают тот же результат, а не случайный.

0 голосов
/ 19 июня 2020

Сделайте функцию - функциональным компонентом React. Тогда вы сможете использовать внутри него React.useMemo. Кроме того, этот ответ и этот ответ могут помочь лучше прояснить

// define it as a functional component
const RenderContacts = ({ item }) => {
     // useMemo inside that
     const randomColor = useMemo(() => randomColorGenerator(), []);

     // TODO: use randomColor somewhere

     return item.phoneNumbers.map(element => (
        <TouchableOpacity ...>
          ...
        </TouchableOpacity>
      ));
     )
}

const Contacts = () => {
  ...

  // extract this out into its own component
  // const renderContacts = item => {
  //    return item.phoneNumbers.map(element => (
  //      <TouchableOpacity
  //        activeOpacity={1}
  //        key={element.digits.toString()}
  //        }}
  //      >
  //        <View>
  //              <View>
  //                <Text>{item.firstName}</Text>
  //                <Text>{element.digits}</Text>
  //              </View>
  //        </View>
  //      </TouchableOpacity>
  //    ));
  // };


  const renderList = () => {
    return (
      <FlatList
        ...
        renderItem={({ item }) => {
          // return <View>{renderContacts(item)}</View>;
          // render the component, don't call it as a function
          return <View><RenderContacts item={item} /></View>;
        }}
      />
    );
  };

  return (
    <View>
      <Text style={Styles.textStyle}>All Contacts</Text>
      {renderList()}
    </View>
  );
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...