Задать вопрос
Ответы пользователя по тегу React
  • Как вставить данные из массива в таблицу?

    0xD34F
    @0xD34F Куратор тега React
    const data = Object.entries(сюда кидаете свои данные);
    
    const years = Array
      .from(new Set(data.flatMap(n => Object.keys(n[1].G))))
      .sort((a, b) => a - b);
    
    const columns = Array
      .from(new Set(data.flatMap(n => Object.values(n[1].G).flatMap(Object.keys))))
      .sort();

    <TableHead>
      <TableRow>
        <TableCell rowSpan={2}>regions</TableCell>
        {years.map(n => <TableCell colSpan={columns.length}>{n}</TableCell>)}
      </TableRow>
      <TableRow>
        {years.flatMap(n => columns.map(m => <TableCell>{m}</TableCell>))}
      </TableRow>
    </TableHead>
    <TableBody>
      {data.map(([ region, { G } ]) => (
        <TableRow>
          <TableCell>{region}</TableCell>
          {years.flatMap(n => columns.map(m => <TableCell>{G[n]?.[m]?.value ?? 0}</TableCell>))}
        </TableRow>
      ))}
    </TableBody>
    Ответ написан
    1 комментарий
  • Какую логику сделать для проверки верности вопроса в приложении тест?

    0xD34F
    @0xD34F Куратор тега React
    Начать следует не с какой-то там логики, а со структуры данных, что содержит вопросы. То, что есть сейчас, никуда не годится. Что, если завтра вместо трёх вариантов ответа надо будет сделать четыре? Будете добавлять ещё по два свойства в каждый объект в массиве вопросов, а в компоненте закопипастите ещё один input? А если в разных вопросах должно будет быть разное количество вариантов ответа? Что тогда?

    Варианты ответа складываете в массив, а корректный вариант обозначаете через его индекс:

    const questions = [
      {
        text: 'Выберите верное утверждение',
        answers: [
          'СССР распался в 1997 году',
          'Солнце вращается вокруг Земли',
          'шестью восемь - двадцать три',
        ],
        correctAnswer: 1,
      },
      {
        text: '...',
        answers: [ '...', '...', ... ],
        correctAnswer: ...,
      },
      ...
    ];

    В компоненте вопроса вместо того, чтобы копипастить input'ы, делаете цикл по вариантам ответа:

    function Question(props) {
      const onChange = e => props.onAnswerChange(+e.target.value);
    
      return (
        <div>
          <h3>{props.question.text}</h3>
          <ol>
            {props.question.answers.map((n, i) => (
              <li>
                <label>
                  <input
                    type="radio"
                    value={i}
                    checked={props.answer === i}
                    onChange={onChange}
                  />
                  {n}
                </label>
              </li>
            ))}
          </ol>
        </div>
      );
    }

    В родительском компоненте храните массив ответов:

    function App(props) {
      const [ answers, setAnswers ] = useState(Array(props.questions.length).fill(null));
    
      const updateAnswer = (questionIndex, answer) =>
        setAnswers(answers.map((n, i) => i === questionIndex ? answer : n));
    
      return (
        <div>
          {props.questions.map((n, i) => (
            <Question
              question={n}
              answer={answers[i]}
              onAnswerChange={answer => updateAnswer(i, answer)}
            />
          ))}
        </div>
      );
    }

    Ну и возвращаясь к вашему вопросу, чего там надо было?

    не получается сделать грамотную проверку правильного ответа...

    Чтобы проверить правильность ответа, надо сравнить его со значением свойства correctAnswer у соответствующего (с тем же индексом) вопроса. Например, считаем количество правильных ответов:

    const correctAnswersCount = answers.reduce((acc, n, i) => {
      return acc + (n === questions[i].correctAnswer);
    }, 0);

    ...и одновременно вывести верные ответы

    Поскольку свойство, обозначающее правильный ответ, является его индексом, просто достаём соответствующие элементы из массивов с вариантами ответа:

    const correctAnswers = questions.map(n => n.answers[n.correctAnswer]);

    Ну а массив строк вывести - надеюсь, справитесь сами.

    UPD. Посмотреть живьём можно здесь (есть отличия от того, что есть или предполагается у вас - вопросы показываются по очереди, а не все сразу; в результатах отображаются только верные ответы).
    Ответ написан
    1 комментарий
  • Как указать активность элемента?

    0xD34F
    @0xD34F Куратор тега React
    В качестве дефолтного значения для activeType указывайте не 0, а нулевой элемент из types:

    React.useState(0); ---> React.useState(types[0]);
    Ответ написан
    1 комментарий
  • Как объединить данные из двух массивов по id?

    0xD34F
    @0xD34F Куратор тега React
    const getData = type => fetch(`https://jsonplaceholder.typicode.com/${type}`).then(r => r.json());

    const [ data, setData ] = useState([]);
    
    useEffect(() => {
      Promise
        .all([ 'posts', 'users' ].map(getData))
        .then(([ posts, users ]) => {
          const usersObj = Object.fromEntries(users.map(n => [ n.id, n ]));
          setData(posts.map(n => ({
            post: n,
            user: usersObj[n.userId],
          })));
        });
    }, []);
    
    return (
      <div>
        {data.map(({ post, user }) => (
          <div>
            <h2>{post.title}</h2>
            <h3>{user.name}</h3>
            <p>{post.body}</p>
          </div>
        ))}
      </div>
    );
    Ответ написан
    1 комментарий
  • Как модифицировать мой API запрос?

    0xD34F
    @0xD34F Куратор тега React
    function Pokemon({ name, url }) {
      const [ data, setData ] = useState(null);
    
      useEffect(() => {
        fetch(url).then(r => r.json()).then(setData);
      }, [ url ]);
    
      return (
        <div>
          <h4>{name}</h4>
          {data
            ? <div>
                <ul>{data.abilities.map(n => <li>{n.ability.name}</li>)}</ul>
                <img src={data.sprites.front_default} />
              </div>
            : <div>loading...</div>
          }
        </div>
      );
    }
    Ответ написан
    Комментировать
  • Как создать фильтр для продуктов?

    0xD34F
    @0xD34F Куратор тега React
    Кроме полных данных храните также и отфильтрованные. Их и отображайте. Значение фильтра пусть хранится в родителе - передавайте его в экземпляр компонента фильтра вместе с функцией, которая его (значение) будет обновлять. При обновлении значения фильтра обновляете массив отфильтрованных данных.

    const Filter = ({ title, values, value, onChange }) => (
      <div>
        <h3>{title}</h3>
        {values.map(n => (
          <label>
            <input
              type="radio"
              onChange={() => onChange(n)}
              checked={value === n}
            />
            {n}
          </label>
        ))}
      </div>
    );

    state = {
      ...
      filteredProducts: [],
      status: 'all',
    }
    
    onFilterStatusChange = status => {
      this.setState({ status });
    }
    
    filterProducts() {
      this.setState(({ status }) => ({
        filteredProducts: status === 'all'
          ? this.state.products
          : this.state.products.filter(n => n.prod_status.includes(status)),
      }));
    }
    
    componentDidUpdate(prevProps, prevState) {
      if (this.state.status !== prevState.status) {
        this.filterProducts();
      }
    }
    
    render() {
      ...
        <Filter
          title="Status:"
          values={[ 'all', 'recommended', 'saleout', 'bestseller', 'new' ]}
          value={this.state.status}
          onChange={this.onFilterStatusChange}
        />
        <Products products={this.state.filteredProducts} />
      ...
    }
    Ответ написан
  • Как разделить строку на две и вывести их как два разных блока?

    0xD34F
    @0xD34F Куратор тега React
    Вместо <div className="status">{status}</div> пусть будет

    {status.split(',').map(n => <div className="status">{n}</div>)}
    Ответ написан
  • Почему тема меняется только после второго клика на переключатель?

    0xD34F
    @0xD34F Куратор тега React
    Как переключается тема? Старый класс удаляется, новый добавляется. Давайте посмотрим, что делаете вы:

    useEffect(() => {
      document.querySelector('.App').classList.toggle(theme)
    }, [theme])

    Переключаете новый класс. Не добавляете, а переключаете. А старый - вообще не трогаете. Исправляем:

    useEffect(() => {
      const el = document.querySelector('.App');
      el.classList.add(theme);
      return () => el.classList.remove(theme);
    }, [ theme ]);
    Ответ написан
  • Как сделать фильтрацию массива с объектами по нескольким критериям одновременно?

    0xD34F
    @0xD34F Куратор тега React
    useEffect(() => {
      const newArray = initialState.filter(n => checked.every(m => n[m]));
      setData(newArray.length ? newArray : initialState);
    }, [ checked ]);

    https://jsfiddle.net/uqbckxtr/1/
    Ответ написан
    1 комментарий
  • Почему не обновляется состояние?

    0xD34F
    @0xD34F Куратор тега React
    isFlipped[index] = !isFlipped[index]
    setIsFlipped(isFlipped)

    Значение isFlipped не изменилось - компонент заново не рендерится. Вместо изменения существующего массива следует создавать новый:

    setIsFlipped(isFlipped.map((n, i) => i === index ? !n : n));
    Ответ написан
  • React. Как удалить созданый элемент из state родителя в дочернем элементе?

    0xD34F
    @0xD34F Куратор тега React
    const Property = ({ data, onDelete }) => (
      <div>
        #{data.id}
        <button onClick={onDelete}>Del</button>
      </div>
    );
    
    const ConstructorPage = () => {
      const [ properties, setProperties ] = useState([]);
      const delProperty = property => setProperties(properties.filter(n => n !== property));
      const addProperty = () => setProperties([
        ...properties,
        {
          id: 1 + Math.max(0, ...properties.map(n => n.id)),
        },
      ]);
      
      return (
        <> 
          <button onClick={addProperty}>Add</button>
          {properties.map(n => (
            <Property
              key={n.id}
              data={n}
              onDelete={() => delProperty(n)}
            />
          ))}
        </>
      );
    };
    Ответ написан
    Комментировать
  • Как сделать тогл булевого свойства в стейте?

    0xD34F
    @0xD34F Куратор тега React
    Разделить объект state - для каждого из его свойств сделать отдельный вызов useState.

    Или копировать все свойства при обновлении: setState({ ...state, show: !state.show });.
    Ответ написан
    1 комментарий
  • Как убрать флажок у поля State?

    0xD34F
    @0xD34F Куратор тега React
    Неужели было так трудно открыть документацию?

    <Column
      allowFiltering={false}
      ...
    />
    Ответ написан
    1 комментарий
  • Как это переделать под JSX?

    0xD34F
    @0xD34F Куратор тега React
    Заменить size на что-нибудь, что начинается с заглавной буквы, например:

    const Headline = ({ children, className, size: Tag }) => {
      return <Tag className={classNames(s[Tag], className)}>{children}</Tag>;
    };
    Ответ написан
    Комментировать
  • Как сделать переход к следующему слайду по заданному событию?

    0xD34F
    @0xD34F Куратор тега React
    const [ text, setText ] = useState('');
    const [ swiper, setSwiper ] = useState(null);
    
    useEffect(() => {
      if (swiper && text какой там вам нужен) {
        swiper.slideNext();
      }
    }, [ swiper, text ]);

    <Swiper
      onSwiper={setSwiper}
      ...

    <input
      value={text}
      onChange={e => setText(e.target.value)}
      ...
    Ответ написан
    1 комментарий
  • Почему может не работать debounce?

    0xD34F
    @0xD34F Куратор тега React
    debounce(getData(), 2000);

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

    Кроме того, debounced функция при каждом рендере компонента должна быть одна и та же, так что завернём её в useCallback, а чтобы она использовала актуальное состояние, будем передавать его как параметр:

    const getData = useCallback(debounce(query => {
      /*
       * здесь всё по-старому, кроме body: JSON.stringify({ query: state.query }),
       * надо заменить на body: JSON.stringify({ query }),
       */
    }, 2000), []);
    
    useEffect(() => {
      getData(state.query);
    }, [ state.query ]);
    Ответ написан
    1 комментарий
  • Как при клике на один элемент скрывать другой?

    0xD34F
    @0xD34F Куратор тега React
    const el = useRef();
    
    useEffect(() => {
      const onClick = e => {
        const dropdown = e.target.closest('.dropdown');
        if (dropdown && dropdown !== el.current) {
          setIsVisible(false);
        }
      };
    
      document.addEventListener('click', onClick);
    
      return () => {
        document.removeEventListener('click', onClick);
      };
    }, []);

    <div className="dropdown" ref={el}>
    Ответ написан
  • Как формувать массив с обьектов в userReducer?

    0xD34F
    @0xD34F Куратор тега React
    Добавляем в массив копию исходного объекта:

    const defaultAnimals = {
      cat: '',
      dog: '',
      mouse: '',
      rhinoceros: '',
    };
    
    const animalsReducer = (state, action) => {
      switch (action.type) {
        case 'updateObj':
          return {
            ...state,
            obj: {
              ...state.obj,
              [action.payload.name]: action.payload.value,
            },
          };
    
        case 'addObjToArr':
          return {
            ...state,
            arr: [ ...state.arr, state.obj ],
            obj: defaultAnimals,
          };
    
        default:
          return state;
      }
    };
    
    const Animals = () => {
      const [ animals, dispatch ] = useReducer(animalsReducer, {
        obj: defaultAnimals,
        arr: [],
      });
    
      const onChange = ({ target: { name, value } }) => {
        dispatch({
          type: 'updateObj',
          payload: { name, value },
        });
      };
      
      const onSubmit = e => {
        e.preventDefault();
        dispatch({
          type: 'addObjToArr',
        });
      };
    
      return (
        <div>
          <form onSubmit={onSubmit}>
            {Object.entries(animals.obj).map(([ k, v ]) => (
              <div key={k}>
                <label>
                  {k}:
                  <input name={k} value={v} onChange={onChange} />
                </label>
              </div>
            ))}
            <button>Save</button>
          </form>
          <pre>{JSON.stringify(animals.obj, null, 2)}</pre>
          <pre>{JSON.stringify(animals.arr, null, 2)}</pre>
        </div>
      );
    };

    Или, добавляем в массив объект, содержащий значение только одного из свойств исходного объекта:

    const animalsReducer = (state, action) => {
      switch (action.type) {
        case 'updateObj':
          return {
            ...state,
            obj: {
              ...state.obj,
              [action.payload.name]: action.payload.value,
            },
          };
    
        case 'addObjToArr':
          return {
            ...state,
            arr: [
              ...state.arr,
              {
                animal: action.payload,
                name: state.obj[action.payload],
              },
            ],
          };
    
        default:
          return state;
      }
    };
    
    const Animals = () => {
      const [ { obj, arr }, dispatch ] = useReducer(animalsReducer, {
        obj: {
          cat: '',
          dog: '',
          mouse: '',
          rhinoceros: '',
        },
        arr: [],
      });
    
      const onChange = ({ target: { name, value } }) => {
        dispatch({
          type: 'updateObj',
          payload: { name, value },
        });
      };
      
      const onSubmit = (e, animal) => {
        e.preventDefault();
        dispatch({
          type: 'addObjToArr',
          payload: animal,
        });
      };
    
      return (
        <div>
          {Object.entries(obj).map(([ k, v ]) => (
            <form onSubmit={e => onSubmit(e, k)} key={k}>
              {k}:
              <input name={k} value={v} onChange={onChange} />
              <button>Save</button>
            </form>
          ))}
          <pre>{JSON.stringify(obj, null, 2)}</pre>
          <pre>{JSON.stringify(arr, null, 2)}</pre>
        </div>
      );
    };
    Ответ написан
  • Как проверить на наличие в объекте и отрисовать?

    0xD34F
    @0xD34F Куратор тега React
    (entities[currentBrand] ?? []).map(n => (
      <ListItem>
        {n.icon}
        {n.label}
      </ListItem>
    ))
    Ответ написан
    Комментировать