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

    0xD34F
    @0xD34F
    Начать следует не с какой-то там логики, а со структуры данных, что содержит вопросы. То, что есть сейчас, никуда не годится. Что, если завтра вместо трёх вариантов ответа надо будет сделать четыре? Будете добавлять ещё по два свойства в каждый объект в массиве вопросов, а в компоненте закопипастите ещё один 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) => acc + (n === questions[i].correctAnswer), 0);

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

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

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

    Ну а массив строк вывести - надеюсь, справитесь сами.
    Ответ написан
    1 комментарий
  • Как указать активность элемента?

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

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

    0xD34F
    @0xD34F Куратор тега JavaScript
    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 Куратор тега JavaScript
    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>
      );
    }
    Ответ написан
    Комментировать
  • Как создать фильтр для продуктов на React?

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

    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 Куратор тега JavaScript
    Вместо <div className="status">{status}</div> пусть будет

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

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

    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
    isFlipped[index] = !isFlipped[index]
    setIsFlipped(isFlipped)

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

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

    0xD34F
    @0xD34F
    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
    Разделить объект state - для каждого из его свойств сделать отдельный вызов useState.

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

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

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

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

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

    0xD34F
    @0xD34F
    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
    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
    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
    const reducer = (state, action) => {
      switch (action.type) {
        case 'update':
          return {
            ...state,
            ...action.payload,
          };
    
        default:
          return state;
      }
    };
    
    const Animals = () => {
      const [ animals, dispatch ] = React.useReducer(reducer, {
        cat: '',
        dog: '',
        mouse: '',
        rhinoceros: '',
      });
    
      const save = e => {
        e.preventDefault();
    
        const { name, value } = e.target.querySelector('input');
    
        dispatch({
          type: 'update',
          payload: {
            [name]: value,
          },
        });
      }
    
      return (
        <div>
          {Object.entries(animals).map(([ k, v ]) => (
            <form onSubmit={save}>
              <label>
                {k}:
                <input type="text" defaultValue={v} name={k} />
              </label>
              <button>Save</button>
            </form>
          ))}
        </div>
      );
    };
    Ответ написан
  • Как проверить на наличие в объекте и отрисовать?

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

    0xD34F
    @0xD34F
    const [ coord, setCoord ] = useState(...);
    
    function onActionTickComplete(e) {
      const projection = e.get('target').options.get('projection');
      const { globalPixelCenter, zoom } = e.get('tick');
      setCoord(projection.fromGlobalPixels(globalPixelCenter, zoom));
    }

    <Map
      onActionTickComplete={onActionTickComplete}
      ...
    >
      <Placemark geometry={coord} />
    </Map>

    https://codesandbox.io/s/sweet-khayyam-zqwy8?file=...
    Ответ написан
    Комментировать
  • Как правильно удалять параметры из url-строки в react-router-dom?

    0xD34F
    @0xD34F Куратор тега JavaScript
    const toggleSearchParams = params => {
      const newSearchParams = [...searchParams];
    
      for (const n of params) {
        const index = newSearchParams.findIndex(m => n[0] === m[0] && n[1] === m[1]);
        if (index === -1) {
          newSearchParams.push(n);
        } else {
          newSearchParams.splice(index, 1);
        }
      }
    
      setSearchParams(newSearchParams);
    };
    
    const handleChangeCheckBoxValue = e => {
      toggleSearchParams([ [ 'selected', e.target.value ] ]);
    };
    
    const handleDeleteParams = () => {
      toggleSearchParams(checkboxParams.map(n => [ 'selected', n ]));
    };
    Ответ написан
    Комментировать