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

    @awenn2015
    Веб-программист самоучка
    Если кто-то будет гуглить и не найдет для себя ответа на вопрос, то вот универсальная реализация, перемещение элемента со смещением соседей по индексам whom и where, может быть полезно в ui где с помощью drag&drop перемещаются элементы в списке или карточки, для вывода сортируясь по полю order

    interface Todo {
      id: number
      order: number
      title: string
    }
    
    interface Test {
      whom: number
      where: number
      expected: number[]
    }
    
    const data: Todo[] = [
      { id: 1, order: 1, title: 'delectus aut autem' },
      { id: 2, order: 2, title: 'quis ut nam facilis et officia qui' },
      { id: 3, order: 3, title: 'fugiat veniam minus' },
      { id: 4, order: 4, title: 'et porro tempora' },
      { id: 5, order: 5, title: 'laboriosam mollitia et enim quasi adipisci quia provident illum' },
      { id: 6, order: 6, title: 'qui ullam ratione quibusdam voluptatem quia omnis' },
      { id: 7, order: 7, title: 'illo expedita consequatur quia in' },
      { id: 8, order: 8, title: 'quo adipisci enim quam ut ab' },
      { id: 9, order: 9, title: 'molestiae perspiciatis ipsa' },
      { id: 10, order: 10, title: 'illo est ratione doloremque quia maiores aut' },
    ]
    
    function swapTodos(todos: Todo[], whom: number, where: number) {
      if (whom === where) return todos
    
      const result = (() => {
        if (whom < where) {
          const start = todos.slice(0, whom)
          const neighbors = todos.slice(whom + 1, where + 1)
          const tail = todos.slice(where + 1, todos.length)
    
          return [...start, ...neighbors, todos[whom], ...tail]
        } else {
          const start = todos.slice(0, where)
          const neighbors = todos.slice(where, whom)
          const tail = todos.slice(whom + 1, todos.length)
    
          return [...start, todos[whom], ...neighbors, ...tail]
        }
      })()
    
      return result.map((it, i) => ({ ...it, order: i + 1 }))
    }
    
    const tests: Test[] = [
      { whom: 1, where: 5, expected: [1, 3, 4, 5, 6, 2, 7, 8, 9, 10] },
      { whom: 0, where: 9, expected: [2, 3, 4, 5, 6, 7, 8, 9, 10, 1] },
      { whom: 4, where: 9, expected: [1, 2, 3, 4, 6, 7, 8, 9, 10, 5] },
      { whom: 8, where: 3, expected: [1, 2, 3, 9, 4, 5, 6, 7, 8, 10] },
      { whom: 9, where: 0, expected: [10, 1, 2, 3, 4, 5, 6, 7, 8, 9] },
      { whom: 9, where: 4, expected: [1, 2, 3, 4, 10, 5, 6, 7, 8, 9] },
    ]
    
    function runTests() {
      console.log('-----------------')
    
      for (const [i, { expected: expect, whom, where }] of tests.entries()) {
        console.log(`[Test ${i + 1} start]`)
    
        const result = swapTodos(data, whom, where)
        const compare = result.map((it) => it.id)
    
        if (JSON.stringify(compare) !== JSON.stringify(expect)) {
          console.warn(`[Test ${i + 1} failed]: Результат не соответствует тому что ожидалось`)
          console.log('Result => ', JSON.stringify(compare))
          console.log('Expected => ', JSON.stringify(expect))
        } else {
          console.log(`[Test ${i + 1} passed]: Тест успешно пройден`)
        }
    
        console.log('-----------------')
      }
    }
    
    export default runTests


    Ps: Обновление сортировки было моим личным требованием, если нужно можно убрать
    Ответ написан
    Комментировать
  • Как поменять порядок элементов в массиве?

    @awenn2015
    Веб-программист самоучка
    Может быть немного корявый но рабочий вариант, можно сделать проще если просто поле order местами менять и сортировать по нему

    type MoveData = ((dir: "left" | "right", i: number) => void)
    
    type TestItemProps = {
      data: { name: string }, i: number, onMove: MoveData
    }
    
    const TestItem: FC<TestItemProps> = ({ data, i, onMove }) => {
      return (
        <div>
          <div style={{ display: "flex", justifyContent: "space-between" }}>
            <span
              style={{ cursor: "pointer" }}
              onClick={() => onMove("left", i)}
            >◀</span>
            <span
              style={{ cursor: "pointer" }}
              onClick={() => onMove("right", i)}
            >▶</span>
          </div>
          <span>{data.name}</span>
        </div>
      )
    }
    
    function Test() {
      const [state, setState] = useState([
        { name: "Petya", order: 0 },
        { name: "Nikita", order: 1 },
        { name: "Sasha", order: 2 },
        { name: "Valera", order: 3 },
      ])
    
      const onMoveHandle: MoveData = (dir, prev) => {
        const isLeftBlock = prev === 0 && dir === "left"
        const isRightBlock = prev === state.length - 1 && dir === "right"
    
        if (isLeftBlock || isRightBlock) return
    
        const next = dir === "left" ? prev - 1 : prev + 1
    
        setState((past) => past.reduce((acc: { name: string, order: number }[], it, i, arr) => {
          if (![prev, next].includes(i))
            acc.push(it)
          else {
            if (i === prev) acc.push(arr[next])
            else acc.push(arr[prev])
          }
    
          return acc
        }, []))
      }
    
      return (
        <div style={{ display: "flex", columnGap: "10px" }}>
          {state.map((it, i) => (
            <TestItem
              data={it} i={i} onMove={onMoveHandle} key={i}
            />
          ))}
        </div>
      )
    }
    Ответ написан
    Комментировать
  • Как сделать так чтобы в input нельзя было вводить меньше 5?

    @awenn2015
    Веб-программист самоучка
    Можно через событие onBlur валидировать

    const Input = () => {
      const range = { min: 5, max: 50 }
      const [value, setValue] = useState<number | "">(range.min)
    
      function onBlurHandle(value: number) {
        if (value >= range.min && value < range.max) return;
        setValue(range.min)
      }
    
      return (
        <input
          type="number"
          value={value}
          onChange={({ target }) => setValue(target.value === "" ? "" : +target.value)}
          onBlur={({ target }) => onBlurHandle(+target.value)}
          min={range.min}
          max={range.max}
        />
      )
    }
    Ответ написан
    Комментировать
  • Как использовать общие либы в create-react-app проектах?

    @awenn2015 Автор вопроса
    Веб-программист самоучка
    Попробовал просто в корне создать папку node_modules/brandname и в нее все что нужно перекинул, не знаю на сколько это правильный вариант но вроде рабочий


    • /node_modules

      • /@types

        • /brand
          • /index.d.ts





      • /brand
        • /utils.ts






    UPD: Вариант рабочий только для поставки типов, с прочим почему то выкидывает ошибку:

    Module parse failed: Unexpected token (3:27)
    File was processed with these loaders:
    * ./node_modules/source-map-loader/dist/cjs.js
    You may need an additional loader to handle the result of these loaders.
    Ответ написан