Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test task #2

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open

Test task #2

wants to merge 26 commits into from

Conversation

romant094
Copy link

Anton Romankov

src/App.js Outdated Show resolved Hide resolved
Copy link
Member

@EvgenyOrekhov EvgenyOrekhov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не получается запустить:
test-task-error

React.Children.only expected to receive a single React element child.
▼ 26 stack frames were expanded.
invariant
node_modules/react/cjs/react.development.js:105
onlyChild [as only]
node_modules/react/cjs/react.development.js:1298
Router.render
node_modules/react-router/es/Router.js:118
finishClassComponent
node_modules/react-dom/cjs/react-dom.development.js:15128
updateClassComponent
node_modules/react-dom/cjs/react-dom.development.js:15083
beginWork
node_modules/react-dom/cjs/react-dom.development.js:15967
performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:19093
workLoop
node_modules/react-dom/cjs/react-dom.development.js:19134
HTMLUnknownElement.callCallback
node_modules/react-dom/cjs/react-dom.development.js:147
invokeGuardedCallbackDev
node_modules/react-dom/cjs/react-dom.development.js:196
invokeGuardedCallback
node_modules/react-dom/cjs/react-dom.development.js:250
replayUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:18341
renderRoot
node_modules/react-dom/cjs/react-dom.development.js:19252
performWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js:20156
performWork
node_modules/react-dom/cjs/react-dom.development.js:20066
performSyncWork
node_modules/react-dom/cjs/react-dom.development.js:20040
requestWork
node_modules/react-dom/cjs/react-dom.development.js:19895
scheduleWork
node_modules/react-dom/cjs/react-dom.development.js:19702
scheduleRootUpdate
node_modules/react-dom/cjs/react-dom.development.js:20406
updateContainerAtExpirationTime
node_modules/react-dom/cjs/react-dom.development.js:20432
updateContainer
node_modules/react-dom/cjs/react-dom.development.js:20500
ReactRoot.push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render
node_modules/react-dom/cjs/react-dom.development.js:20813
(anonymous function)
node_modules/react-dom/cjs/react-dom.development.js:20967
unbatchedUpdates
node_modules/react-dom/cjs/react-dom.development.js:20283
legacyRenderSubtreeIntoContainer
node_modules/react-dom/cjs/react-dom.development.js:20963
render
node_modules/react-dom/cjs/react-dom.development.js:21030
▲ 26 stack frames were expanded.
Module../src/index.js
src/index.js:5
  2 | import ReactDOM from 'react-dom';
  3 | import App from './App';
  4 | 
> 5 | ReactDOM.render(<App />, document.getElementById('root'));
View compiled
__webpack_require__
/home/orehov/Downloads/frontend-test-task/webpack/bootstrap:782
  779 | };
  780 | 
  781 | // Execute the module function
> 782 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
      | ^  783 | 
  784 | // Flag the module as loaded
  785 | module.l = true;
View compiled
fn
/home/orehov/Downloads/frontend-test-task/webpack/bootstrap:150
  147 | 		);
  148 | 		hotCurrentParents = [];
  149 | 	}
> 150 | 	return __webpack_require__(request);
      | ^  151 | };
  152 | var ObjectFactory = function ObjectFactory(name) {
  153 | 	return {
View compiled
0
http://localhost:3000/static/js/main.chunk.js:977:18
__webpack_require__
/home/orehov/Downloads/frontend-test-task/webpack/bootstrap:782
  779 | };
  780 | 
  781 | // Execute the module function
> 782 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
      | ^  783 | 
  784 | // Flag the module as loaded
  785 | module.l = true;
View compiled
checkDeferredModules
/home/orehov/Downloads/frontend-test-task/webpack/bootstrap:45
  42 | 	}
  43 | 	if(fulfilled) {
  44 | 		deferredModules.splice(i--, 1);
> 45 | 		result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
     | ^  46 | 	}
  47 | }
  48 | return result;
View compiled
Array.webpackJsonpCallback [as push]
/home/orehov/Downloads/frontend-test-task/webpack/bootstrap:32
  29 | 	deferredModules.push.apply(deferredModules, executeModules || []);
  30 | 
  31 | 	// run deferred modules when all chunks ready
> 32 | 	return checkDeferredModules();
     | ^  33 | };
  34 | function checkDeferredModules() {
  35 | 	var result;
View compiled
(anonymous function)
http://localhost:3000/static/js/main.chunk.js:1:57

@romant094
Copy link
Author

romant094 commented Feb 5, 2019

Не получается запустить

Исправил. Был неверный import

Copy link
Member

@EvgenyOrekhov EvgenyOrekhov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

С точки зрения пользователя есть два замечания по работе приложения:

  • поля ввода
    • если стереть значения, поля не подсвечиваются красным и не блокируется кнопка "Filter"
    • если в первое поле попытаться ввести a, перейти во второе поле и нажать b, то в первом поле появится a
  • модальное окно
    • в тексте говорится "You found 5 activities", но фактически пользователь увидел только 4 активности
  • мобильный режим
    • в интерфейсе "Filters" элементы расположены неэргономично

src/components/commonData.js Outdated Show resolved Hide resolved
src/components/commonData.js Outdated Show resolved Hide resolved
<button className='btn btn-small' onClick={modalClose}>Cancel</button>
</div>
<div className="col-1-of-2">
<Link to="/filter/" className='btn btn-small'>Try!</Link>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно обойтись без глобальных CSS-классов, воспользовавшись свойством as у styled-components: https://www.styled-components.com/docs/basics#extending-styles (второй пример).

В случае с Button и Link можно сделать так:

const Button = styled.button`
    /* ...styles... */
`;
const SmallButton = styled(Button)`
    /* ...more styles... */
`;

<SmallButton>Cancel</SmallButton>
<SmallButton as={Link} to="/filter/">Try!</SmallButton>

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Окей, учту на будущее.

}

export default GlobalStyle;
export { Button, Headline, Container, ContainerInnerWrap, ActivityWrap, Strong, ActivityContent };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В идеале каждый модуль должен отвечать за и экспортировать что-то одно. Этот модуль можно разделить как минимум на три: GlobalStyle.js, StyledComponents.js, и ActivityContent.js.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Учту

const Price = styled.span`
font-size: 24px;
`
const ActivityContent = (props) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Стоит активнее использовать деструктуризацию, особенно в сигнатурах функций. props не говорит ни о чём, а взглянув на const ActivityContent = ({filter, data}) => { сразу становится понятно что в компонент нужно передать.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исправил

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

data тоже было бы лучше деструктурировать:

const ActivityContent = ({filter, data}) => {
    const {
        activity,
        key,
        type
        /* ... */
    } = data;

    return /* ... */;
};

Опять же для повышения самодокументированности кода.

</Price>
</PriceWrap>
</div>
<div className={Object.keys(props.data).length === 1 ? null : 'display-none'}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Повторная проверка условия Object.keys(props.data).length === 1. Возможно было бы лучше воспользоваться вот этой техникой: https://reactjs.org/docs/conditional-rendering.html#inline-if-else-with-conditional-operator.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исправил

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я имел в виду вместо

<div className={isError ? 'display-none' : ''}>
    <Success />
</div>
<div className={isError ? '' : 'display-none'}>
    <Error />
</div>

сделать

{
    isError
    ? <Error />
    : <Success />
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исправил

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Только теперь div-контейнеры в Success и Error (которые выполняют проверку на data.error) вообще не нужны, так как эта проверка выполняется уровнем выше, в ActivityWrap.

`
function Activity() {
const [data, setData] = useState({});
let [clickCount, setClickCount] = useState(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему let, а не const?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возможно копипаст... Исправил.

<ContainerInnerWrap>
<Headline>WhattodoApp</Headline>
<PreambulaText>{Object.keys(data).length === 0 ? `Don't know what to do? We'll help you! Just click the button and you'll see the possible variant for your vocation...` : `Don't like that? Click... ;-)`}</PreambulaText>
<Button onClick={getRandomActivity} style={{ marginBottom: '20px' }}>Random</Button>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Для стилизации лучше использовать какой-то один способ. Если это styled-components, то все стили должны объявляться с помощью styled-components.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ОК, учту. Но как быть в том случае, если в одном месте одному элементу нужно задать отступ? Делать новый компонент по аналогии с этим?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да.

src/components/filteredActivites.js Outdated Show resolved Hide resolved
let url = 'http://www.boredapi.com/api/activity';

if (filterType === 'priceRange') {
url = `${url}?minprice=${firstValue}&maxprice=${secondValue}`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше использовать готовый инструмент для работы с query string, например https://www.npmjs.com/package/qs.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Окей, учту.

@EvgenyOrekhov
Copy link
Member

Теперь если в первое поле попытаться ввести a, перейти во второе поле и нажать b, то в первом поле появится NaN.

@romant094
Copy link
Author

Теперь если в первое поле попытаться ввести a, перейти во второе поле и нажать b, то в первом поле появится NaN.

Если честно, с этим не знаю, что делать с этим...

@EvgenyOrekhov
Copy link
Member

Теперь если в первое поле попытаться ввести a, перейти во второе поле и нажать b, то в первом поле появится NaN.

Если честно, с этим не знаю, что делать с этим...

Может быть в данном случае бОльшую часть валидации вообще стоит переложить на плечи браузера?

<input type="number" min="1" required>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants