• Почему translate срабатывает сразу?

    rockon404
    @rockon404
    Frontend Developer
    transition работает когда вы изменяете свойство. На примере с hover:
    .class {
      color: red;
      transform: translateY(-100%);
      transition: all 1s;
    }
    
    .class:hover {
      color: blue;
      transform: translateY(-50%);
    }

    При наведении курсора мыши на элемент .class, в течении секунды плавно изменится цвет с красного на синий и translateY c -100% на -50%.
    Ответ написан
    5 комментариев
  • Почему не могу использовать await в if блоке?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Дело не в условном операторе, а в том, что у вас колбек у map не асинхронная функция и в ней нельзя использовать ключевое слово await. Исправить можно так:
    export const renderNotes = (user , users) => dispatch => {
      Object.keys(users).forEach(async element => {
        if (user === users[element].login) {
          const elements = await fire.database().ref('users/' + element + '/notes/'); 
    
          return dispatch({
            type: RENDER_NOTES,
            payload: elements,
          });
        }
      })
    };


    В случае когда надо лишь пройтись по элементам массива, использовать метод map неправильно, для таких случаев есть метод forEach.

    map следует использовать тогда, когда на основе исходного массива, надо получить новый массив элементов, преобразованных по определенному алгоритму:
    const srcArray = [ 0.134555, 0.294587, 0.570858];
    
    const mappedArray = srcArray.map(el => (el * 100).toFixed(1) + '%');
    
    console.log(mappedArray);
    
    // => ["13.5%", "29.5%", "57.1%"]
    Ответ написан
    Комментировать
  • Почему возвращает undefined is not an object (evaluating 'this.props.users')?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы передаете функию колбеком в слушатель события onClick, она теряет контекст и this больше не ссылается на ваш компонент.
    Исправить можно, изменив хандлер с class method на inline class function:
    submitBalance = () => {
      // your stuff
    };

    либо можно забинтить функицю в конструкторе:
    constructor(props) {
      super(props);
      this.submitBalance.bind(this);
    }


    Так же можно обернуть this.submitBalance в стрелочную функцию в render, но этот вариант лучше использовать когда надо передать свои аргументы:
    onClick={e => this.submitBalance(someArg, e)}
    Ответ написан
    1 комментарий
  • Почему в этой операции javascript выводится 16?

    rockon404
    @rockon404
    Frontend Developer
    Тут надо понимать, что в локальной области видимости функций plus1 и square x это значение преданного аргумента, а не глобальной переменной x.
    var x = 2, y = 3;
    function plus1(x) {
    return x + 1;  // тут x это значение которое вы передали при вызове аргументом
    }
    plus1(y)
    var square = function(x) {
    return x * x;  // тут тоже
    };
    square(plus1(y))


    Разберем выражение:
    square(plus1(y))

    У вас y = 3.

    Получается:
    square(plus1(3));

    На шаге plus1(3):
    function plus1(3) {
    return 3 + 1;
    }

    На выходе из первой функции получаем 4

    Получается:
    square(4);

    на этом шаге поисходит следущее:
    function(4) {
    return 4 * 4;
    };


    На выходе получаем 16
    Ответ написан
    2 комментария
  • Как получить название переменной в массиве?

    rockon404
    @rockon404
    Frontend Developer
    Никак. В массиве их нет. Там внутри значения x и y на момент присваивания:
    {
      0: 10,
      1: 3,
      length: 2,
      __proto__: Array(0)
    }


    Вам для вашей задачи лучше складывать данные в объект:
    var x = 10;
    var y = 3;
    var obj = { x: x, y: y };
    
    var keys = Object.keys(obj);
    
    console.log(keys);
    // => [ 'x', 'y']
    Ответ написан
    Комментировать
  • Нужны ли props?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Если не используете props, не пишите.
    Когда используете, можно делать деструктуризацию:
    function Welcome({ name }) {
      return <h1>Hello, {name}</h1>;
    }


    Второй вопрос:
    export default function Welcome() {
      return <h1>Hello, World!</h1>;
    }
    Ответ написан
    Комментировать
  • Для чего react server side rendering?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    1. SSR нужен в проектах для которых важна индексация поисковиками.
    2. Такие приложения называют не SPA, а изоморфными.
    3. SSR в изоморфных приложениях используется с REST API, так что проблем с мобильным клиентом у вас не возникнет.
    4. Рендерится все тоже самое, что и в SPA только на стороне сервера, после передачи клиенту приложение работает как обычное SPA и взамодействует с сервером по REST API.
    Ответ написан
    Комментировать
  • Как контролировать число одновременных вызовов асинхронных функций в очереди?

    rockon404
    @rockon404
    Frontend Developer
    function Parallel(settings) {
      this.parallelJobs = settings.parallelJobs;
      this.results;
      this.tasks = [];
      this.onDone;
      this.index = 0;
      this.activeJobs = 0;
    };
    
    Parallel.prototype.start = function() {
      this.results = Array(this.tasks.length);
    
      for (var i = 0; i < Math.min(this.parallelJobs, this.tasks.length); i++) {
        this.next();
      }
    }
    
    Parallel.prototype.next = function(result) {
      var index = this.index;
      this.activeJobs++;
    
    
      this.tasks[this.index](function(result) {
        this.onResult(result, index);
      }.bind(this));
    
      this.index++;
    }
    
    Parallel.prototype.onResult = function(result, index) {
      this.results[index] = result;
      this.activeJobs--;
    
      if(this.tasks[this.index]) {
        this.next();
      } else if (this.activeJobs === 0) {
        this.onDone(this.results);
      }
    }
    
    Parallel.prototype.job = function (step) {
      this.tasks.push(step);
      return this;
    };
    
    Parallel.prototype.done = function (onDone) {
      this.onDone = onDone;
      this.start();
    };
    
    
    
    function asyncRequest1(result) {  
         setTimeout(result, 2000, 'data');
    }
    
    function asyncRequest2(result) {  
         setTimeout(result, 2000, 'data 2');
    }
    
    function asyncRequest3(result) {  
         setTimeout(result, 2000, 'data3');
    }
    
    function asynRequest4(result) {  
         setTimeout(result, 2000, 'data4');
    }
    
    
    
    var runner = new Parallel({
      parallelJobs: 2
    });
    
    runner.job(asyncRequest1)
          .job(asyncRequest2)
          .job(asyncRequest3)
          .job(asyncRequest4)
          .done(function (results) {
             console.log(results); 
          });
    Ответ написан
    3 комментария
  • Почему возникает ошибка при действии delete?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы задаете начальное такое начальное состояние:
    { tweets: tweets.data }
    А потом пытаетесь на нем вызвать метод массива filter, когда состояние является объектом.

    Исправьте редьюсер так:
    const reducer = (state = { tweets: tweets.data }, action) => {
      switch (action.type) {
        case 'DELETE': {
          return {
            ...state,
            tweets: state.tweets.filter(value => value.id !== action.id),
            };
        }
        default:
          return state;
      }
    };


    Демо: https://codesandbox.io/s/n5wlj8wq34
    Ответ написан
    3 комментария
  • Установка шрифтов в CSS: каждый стиль по имени или свойство weight?

    rockon404
    @rockon404
    Frontend Developer
    Правильно так:
    @font-face {
      font-family: 'OpenSans';
      src: url("../fonts/OpenSans/OpenSansRegular/OpenSansRegular.eot");
      ...
      font-weight: 400;
      font-style: normal;
    }
    @font-face {
      font-family: 'OpenSans';
      src: url("../fonts/OpenSans/OpenSansLight/OpenSansLight.eot");
      ...
      font-weight: 300;
      font-style: normal;
    }


    Пример использования:
    html {
      font-family: 'OpenSans', sans-serif;
      font-size: 14px;
    }
    
    .example-with-regular-text {
      // nothing
    }
    
    .example-with-light-text {
      font-weight: 300;
    }
    Ответ написан
    1 комментарий
  • Как сделать, что бы ховер на элемент применялся и к детям?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Не стоит полагаться на эти события, они не всегда срабатывают.
    В первую очередь надо избавиться от зазора между родительским и дочерним элементом. Меню dropdown по-хорошему должно иметь позицию top: 100%. Для имитации зазора можно использовать контейнер с padding.
    А можно что-то вроде:
    .user-logout {
      border-top: 5px solid transparent;
      background-clip: padding-box;
    }

    Путей много на самом деле.

    Саму задачу проще решить через css, без лишнего пререндера компонента.
    Ответ написан
    1 комментарий
  • Как сделать отображение страницы после ссылки полностьюзанимающая страницу?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    На сколько я понял вопрос, вам надо переделать так:
    import { BrowserRouter, Route, Link, Switch } from 'react-router-dom';
    
    export default class App extends Component {
      render() {
        return (
          <BrowserRouter>
            <div>
              <ul>
                <li><Link to='/'>Home</Link></li>
                <li><Link to='/about'>About</Link></li>
                <li><Link to='/contact'>Contact</Link></li>
              </ul>
              <hr/>
              <Switch>
                <Route exact path='/' component={Home}/>
                <Route path='/about' component={About}/>
                <Route path='/contact' component={Contact}/>
                <Route path='/test/:id' component={HomePage}/>
              </Switch>
            </div>
          </BrowserRouter>
        );
      }
    }


    export default class Home extends Component{
      render(){
        return(
          <div>
            <h1>Home</h1>
            <div>
              <ul>
                <li><Link to='/test/1'>Фото на документы</Link></li>
                <li><Link to='/test/2'>Принтер</Link></li>
                <li><Link to='/test/3'>Печать на документы</Link></li>
              </ul>
            </div>
          </div>
        );
      }
    }
    Ответ написан
    Комментировать
  • Переменная NODE_ENV на продакшене должна быть установлена в 'production' только во время сборки проекта или же и во время его жизни?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Для того чтобы сделать production сборку, запускайте webpack с ключoм -p:
    webpack -p
    либо устанавливайте переменную process.env.NODE_ENV и используйте UglifyJsPlugin:
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    }),
    new webpack.optimize.UglifyJsPlugin({
           // options 
        }),

    при запуске с ключом -p, в кофиг добавляются именно эти строки.

    Еще вариант:
    plugins: [
      new webpack.EnvironmentPlugin(['NODE_ENV']),
      new webpack.optimize.UglifyJsPlugin({
          // options 
        }),
    ],


    Строка:
    new webpack.EnvironmentPlugin(['NODE_ENV']),
    аналогична:
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    }),


    А c NODE_ENV вы production сборку не сделаете, надо использовать именно process.env.NODE_ENV.
    Ответ написан
    1 комментарий
  • Как работает этот код с axios?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Я вам это пример тогда скинул, чтобы показать приближенный к жизни кейс использования этого компонента. Все совсем не обязательно должно быть реализовано именно так.

    1. Смотрите у вас компонент реализует бесконечную подгрузку информации с сервера. Но как вы собрались реализовывать взаимодействие клиента и сервера? Как серверу узнать сколько данных вы получили и какие отдавать дальше? Простейший и проверенный временем вариант пагинация. Надо использовать пагинатор на стороне сервера.
    Допустим на сервере 500 изображений. Как запросить первые 20?
    GET 'api/images?limit=20&page=1'
    Сервер должен вернуть что-то вроде:
    {
      data: [...],
      quantity: 500,
    }

    Теперь вы знаете, что изображений всего 500.
    Запрос на следующие 20 изображений будет:
    GET 'api/images?limit=20&page=2'

    Как только вы загрузите 25-ую страницу, условие в render:
    const hasMore = page * limit < total;
    вернет false, так как:
    25 * 20 < 500 // false
    И ваш компонент перестанет обращаться к серверу и показывать прелоадер при прокрутке в конец списка, так как он полностью загружен.
    Как-то так. Клиент видит бесконечный список, а по факту сервер возвращает данные постранично.

    2. spread operator
    https://developer.mozilla.org/ru/docs/Web/JavaScri...
    es6-features.org/#SpreadOperator
    jsraccoon.ru/es6-spread-rest
    const arr1 = ['a'];
    const arr2 = ['b'];
    const arr3 = [...arr1, ...arr2];
    const arr4 = [...arr1, 1, ...arr2, 'c'];
    
    console.log(arr3); 
    // => ['a', 'b'];
    
    console.log(arr4); 
    // => ['a', 1, 'b', 'c'];
    
    const obj1 = { a: 'a', b: 'old b' };
    const obj2 = { b: 'new b', c: 'c' };
    const obj3 =  { ...obj1, ...obj2 };
    const obj4 = { ...obj2, ...obj1 };
    const obj5 =  { ...obj1, ...obj2, d: 'd' };
    
    console.log(obj3);
    // => { a: 'a', b: 'new b', c: 'c' };
    
    console.log(obj4);
    // => { a: 'a', b: 'old b', c: 'c' };
    
    console.log(obj5);
    // => { a: 'a', b: 'new b', c: 'c', d: 'd' };


    3. Хорошо изучить JavaScript, можно пройти уроки на learn.javascript.ru. Изучайте пути решения типовых задач веба: валидация, авторизация, пагинация, CRUD, REST, передача и хранение файлов и прочее. И пробуйте это на практике.
    Ответ написан
    Комментировать
  • Как правильно одновременно работать с cookies и БД?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы не с той стороны подходите к задаче.
    Пишите в БД timestamp deadLineDate, по дате создания и определяйте статус.
    Ответ написан
  • Почему не обновляются props после dispatch?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    Вы мутируете массив tasks который передаете в компонент. При получении новых свойств, после обновления стора, в компоненте в который вы предаете его происходит проверка:
    this.props.tasks === nextProps.tasks; // true
    Она возвращает true, так как это тот же самый массив и компонент не обновляется.

    Исправьте так:
    export default function addDelete(state = initialState, action){
      switch (action.type) {
        case "ADD_TASK":
          return {
            ...state,
            tasks: [...state.tasks, {{id: action.id, time : action.time, task: action.task}}],
          };
        case "DELETE_TASK":
          return {
            ...state,
            tasks: [...state.tasks.filter(task => task.id != action.id)],
          };
        case "SET_ACSSES":
          return {
            ...state,
            add: !state.add,
          };
        default:
          return state;
      }
    }


    Но будет еще лучше, если поправите свои actionCreators. Кладите полезную нагрузку в ключ payload:
    export default function add(time, task, id){
      if(!task || !time){
        return {
          type: "SET_ERROR",
          payload: "Error, invalid data"
        };
      }
    
      return{
        type: "ADD_TASK",
        payload: {
          id: id,
          time: time,
          task: task,
        },
      }
    }


    export const deleteTask = id => ({
      type: 'DELETE_TASK',
      payload: id,
    });


    Тогда код редьюсера будет такой:
    export default function addDelete(state = initialState, action) {
      const { type, payload } = action;
    
      switch (type) {
        case "ADD_TASK":
          return {
            ...state,
            tasks: [...state.tasks, payload],
          };
        case "DELETE_TASK":
          return {
            ...state,
            tasks: [...state.tasks.filter(task => task.id != payload)],
          };
        case "SET_ACSSES":
          return {
            ...state,
            add: !state.add,
          };
        default:
          return state;
      }
    }
    Ответ написан
    1 комментарий
  • Почему не работают вложенные маршруты в React приложении?

    rockon404
    @rockon404 Куратор тега React
    Frontend Developer
    У вас роут /settings со свойством exact. Роуты с этим свойством срабатывают только при точном совпадении маршрута. Уберите его и все будет работать.
    Ответ написан
    Комментировать
  • В чем отличия между .className('') и .classList.add('')?

    rockon404
    @rockon404
    Frontend Developer
    Ответ написан
    Комментировать