Esmeralda33
@Esmeralda33

Как сделать, чтобы при каждом клике мыши приложение заново не пересоздавало массив?

Я новичок в React, делаю приложение с рандомным массивом, чтобы потом сравнивать с ним другой массив.
Проблема в том, что вначале создается рандомным массив (код ниже), но и потом при каждом клике мыши приложение заново пересоздает этот рандомный массив.
А весь смысл приложения в том что сравнивать нужно с одним массивом! Что делать?

import React, {useState} from 'react';
import {StyleSheet, View, Text, Button} from "react-native";

function Block() {
const ranomdArr = function() {
    let array = ['faith', 'hope', 'love', 'gratitude', 'patience', 'mercy'];
    var currentIndex = array.length, temporaryValue, randomIndex;
  
    while (0 !== currentIndex) {
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;
  
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
      }
    return array;
  }

const [fetus, setFetus] = useState(['0', '1', '2', '3', '4', '5']);
let refCopy= React.createRef();
let refOut= React.createRef();

function show(e) {
  let index = e.target.parentElement.firstChild.getAttribute('index');
  let copy = Object.assign([], fetus);
  copy[index] = e.target.innerHTML;
  setFetus(copy);
}

function Goods(props) {
  return(
    <View style={styles.sell}>
      <h7 index={props.index}></h7>
      <Text style={styles.text} onPress={show}>{props.faith}</Text>
      <Text style={styles.text} onPress={show}>{props.hope}</Text>
      <Text style={styles.text} onPress={show}>{props.love}</Text>
      <Text style={styles.text} onPress={show}>{props.gratitude}</Text>
      <Text style={styles.text} onPress={show}>{props.patience}</Text>
      <Text style={styles.text} onPress={show}>{props.mercy}</Text>
    </View>
  )
}
const fruit = [
    {index:0,text:'faith',text:'hope',text:'love',text:'gratitude',text:'patience',text:'mercy'},
    {index:0,text:'faith',text:'hope',text:'love',text:'gratitude',text:'patience',text:'mercy'},
    {index:0,text:'faith',text:'hope',text:'love',text:'gratitude',text:'patience',text:'mercy'},
    {index:0,text:'faith',text:'hope',text:'love',text:'gratitude',text:'patience',text:'mercy'},
  ];
  const result = fetus.map((element, index) => {
    return <View style={styles.sell}> <Text style={styles.text} key={index}>{element}</Text></View>;
 });

function score() {
  console.log(ranomdArr());
  let iter = '0';
  for(let i=0; i<refCopy.current.children.length; i++) {
    if(refCopy.current.children[i].innerText === ranomdArr()[i]) {
      iter++;
    }
  }
 refOut.current.innerHTML += refCopy.current.outerHTML+ 'Score: '+ iter;
}
  return (
      <>
      <View ref={refOut}></View>
      <View style={styles.tabl} ref={refCopy}>{result} </View>
      <Button title="Try it!" color="#f212ff" onPress={score}/>
      <View style={styles.tabl}> 
      {fruit.map(item=><Goods index={item.index} faith={item.faith} hope={item.hope} love={item.love} gratitude={item.gratitude} patience={item.patience} mercy={item.mercy}/>)}
      </View>
      </>
    )
}
  • Вопрос задан
  • 91 просмотр
Пригласить эксперта
Ответы на вопрос 2
@Viarll
Случайный массив генерируется так часто из-за того, что генерация происходит каждый раз при обращении к ranomdArr, т.к. это функция, а не переменная/константна. Т.е. в функции score, которая вызывается как раз кликом:
это происходит часто(8 генерация за клик)

function score() {
  console.log(ranomdArr()); //<b>Генерация нового массива</b>
  let iter = '0';
  for(let i=0; i<refCopy.current.children.length; i++) {
    if(refCopy.current.children[i].innerText === ranomdArr()[i]) { //<b>Генерация нового массива в цикле</b>
      iter++;
    }
  }


Первое же, что приходит в голову вынести переменную и отдельно функцию генерации ее значения из компоненты Block. Как быстрое решение можно разместить просто над компонентой:
Как может выглядеть код

....
import { View, Text, Button } from "react-native";

const generateRandomArray = function () {
  let array = ["faith", "hope", "love", "gratitude", "patience", "mercy"];
  var currentIndex = array.length, temporaryValue, randomIndex;

  while (0 !== currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
};

let ranomdArr = generateRandomArray();

function Block() {
  const [fetus, setFetus] = useState(["0", "1", "2", "3", "4", "5"]);
  let refCopy = React.createRef();
  let refOut = React.createRef();.
.....

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

Так мы решим проблему с частой генерацией - генерировать мы сможем когда нам удобно.
НО такое решение считается анти паттерном и нарушает основную идею функциональных компонент - делать их "чистыми", предсказуемыми, когда результат выполнения функции выводящей компоненту зависит только от входных параметров, а не от переменных снаружи нее.
Обобщить логику кода и тем самым вынести его из кода компоненты
  1. Функция генерирующая случайный массив могла получать любой массив в качестве параметра - таким образом мы сделаем "чистой" и сможем вынести в отдельный файл
  2. Массив на основе которого мы генерируем новый случайный массив никогда не меняется - значит он константа в контексте приложения(ничто его не изменит), но он нужен только в этой компоненте. В таких случаях допустимо размещать инициализацию константы снаружи компоненты. Примером таких констант еще могу выступить столбцы для компоненты таблицы.
  3. Сгенерированный случайный массив можно хранить в компоненте, но надо чтобы он был неизменяемый при ререндере. Для этого используем хук useRef. При каждом рендере нам будет возвращаться то значение, которое было до него. Получать/изменять значение можем через current - "toggled.current = !toggled.current".

Так у нас будет возможность сгенерировать новый случайный массив в любое необходимое нам время. Кода в файле компонента станет меньше, что приближает к "чистому" коду.
Ответ написан
Комментировать
SemanticMoscow
@SemanticMoscow
проверяйте, существует ли то, что не нужно заново создавать,
если true, то пропускаем "создание" и идём дальше
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы