рдкрд░реАрдХреНрд╖рдг рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ UI рдШрдЯрдХ

рдЕрдм рдореИрдВ рдХреНрдпрд╛ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ


рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдПрдХ рдХреЛрдб рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рд░рд┐рдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХреЗ рдмрд╛рдж рдЗрд╕ рддрд░рд╣ рдХреЗ рдкрд░реАрдХреНрд╖рдг рд╣рд░ рдмрд╛рд░ рдЯреВрдЯрддреЗ рд╣реИрдВ, рдЦрд╛рд╕рдХрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдШрдЯрдХреЛрдВ рдореЗрдВред рдирддреАрдЬрддрди, рдореИрдВ .test.js рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдЦреБрджрд╛рдИ рдХрд░рдиреЗ рдореЗрдВ рдмрд╣реБрдд рд╕рдордп .test.js , рд╕рд╛рде рд╣реА рд╕рд╛рде рдЯреЗрд╕реНрдЯ рдХрд╡рд░реЗрдЬ рдХреЗ рд▓рд┐рдП 80% рдХреЗ рдЬрд╛рджреБрдИ рдЖрдВрдХрдбрд╝реЗ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддрд╛ .test.js ред


рдореБрдЭреЗ рдХреНрдпрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП?


рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рд╕рд╣рд┐рдд рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд▓рд┐рдЦрддреЗ рд╕рдордп, рдореБрдЭреЗ рдЙрд╕ рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХрдо рд╕реЛрдЪрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд┐рд╕рдХрд╛ рдореИрдВ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдФрд░ рдЗрд╕ рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХред рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдирдХрд▓ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ред рдирд┐рдореНрдирддрдо рд╕реНрддрд░ рдкрд░ рднреАред


рдЙрджрд╛рд╣рд░рдг


рдПрдХ рдорд╛рдирдХ yuy accordion рдШрдЯрдХ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВред рдЬрдм рджрдмрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЦреБрд▓рддрд╛ рд╣реИ рдпрд╛ рдмрдВрдж рд╣реЛрддрд╛ рд╣реИред рд╕рд╛рдордЧреНрд░реА рдХреЛ рдШрдЯрдХ рдХреЗ рд░реВрдк рдореЗрдВ children рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдЫрд╡рд┐


рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдШрдЯрдХ рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:


  • рдкрд╣рд▓реЗ 3 рд╕рдордЭреМрддреЗ рддреИрдирд╛рдд рд╣реИрдВ, рд╢реЗрд╖ рд╕рднреА рдмрдВрдж рд╣реИрдВред
  • рдЬрдм рдЖрдк рд╕рдордЭреМрддреЗ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ publishAccordionAnalytics рдореЙрдбреНрдпреВрд▓ publishAccordionAnalytics , рдЬреЛ рдПрдирд╛рд▓рд┐рдЯрд┐рдХреНрд╕ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИред рд╣рдо рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЛ @myProject/analyticsHelpers рдкреИрдХреЗрдЬ рд╕реЗ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ
  • рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдирд┐рдЪрд▓реЗ рднрд╛рдЧ рдореЗрдВ рдЫрд┐рдкреЗ рд╣реБрдП рдЕрдХреЙрд░реНрдбрд┐рдпрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдХреЙрд░реНрдбрд┐рдВрдЧ рд╕рд╛рдордЧреНрд░реА рдЦреЛрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рддреЛ рдПрдиреАрдореЗрд╢рди рдЪрд╛рд▓реВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдШрдЯрдХ рд╕рд╛рдордЧреНрд░реА рд╕реНрдХреНрд░реАрди рдХреЗ рджреГрд╢реНрдп рднрд╛рдЧ рдореЗрдВ рдЪрд▓реА рдЬрд╛рддреА рд╣реИред

 ... import { publishAccordeonAnalytics } from '@myProject/analyticsHelpers'; class Accordion extends Component { positionReference: RefObjectType; constructor(props) { super(props); this.positionReference = React.createRef(); } scrollToRef = (ref) => { const wrapper = document.querySelector('.app'); return isInViewPort(ref, wrapper) ? null : setTimeout(() => { return ref.current && wrapper && wrapper.scrollTo(wrapper.scrollTop, wrapper.scrollTop + ref.current.offsetTop) }, 300); }; render() { const { headerName, children, index } = this.props; const { scrollToRef, positionReference } = this; const defaultOpenAccordions = index >= 3; return ( <Accordion defaultOpen={!defaultOpenAccordions} headerName={headerName} onChange={(open) => { publishAccordionAnalytics(open, headerName); if (defaultOpenAccordions) { scrollToRef(positionReference); } }} id={headerName} > {children} {defaultOpenAccordions && <div data-testId="referenced-div" ref={positionReference} />} </Accordion> ); } } 

рдЕрдм рдореИрдВ рдПрдХ рдкрд░реАрдХреНрд╖рд╛ рдХреИрд╕реЗ рд▓рд┐рдЦреВрдВрдЧрд╛:


 jest.mock('@myProject/analyticsHelpers'); describe('', () => { test(' ', () => { const jsx = ( <Accordion headerName=" "> <div>Test</div> </Accordion> ); const tree = renderer .create(jsx) .toJSON(); expect(tree).toMatchSnapshot(); }); test(' ', () => { const wrapper = mount( <Accordion headerName=" " index={1}> <div>Test</div> </Accordion> ); wrapper.find('Header').simulate('click'); expect(publishAccordeonAnalytics).toHaveBeenCalledTimes(1); }); test(' scrollToRef ', () => { const wrapper = shallow( <Accordion headerName=" " index={7}> <div>Test</div> </Accordion>); const component = wrapper.instance(); component.scrollToRef = jest.fn(); wrapper.find('Header').simulate('click'); expect(publishAccordeonAnalytics).toHaveBeenCalledTimes(1); expect(component.scrollToRef).toHaveBeenCalled(); }) }); 

рдореИрдВ рд╕реНрдиреИрдкрд╢реЙрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдШрдЯрдХ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реВрдВ, рд╕рд╛рде рд╣реА рдХреНрд▓рд┐рдХ рдкрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рднреА рдХрд░рддрд╛ рд╣реВрдВред


рдпрд╣ рд╕рдордЭреМрддреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдкреВрд░рд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдЗрд╕рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЕрдм рдореИрдВ React.Component , рдмрджрд▓реЗ рдореЗрдВ React.Component рдХреЛ functional component , рдФрд░ рдПрдХ рдЕрд▓рдЧ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ scrollToRef рдШрдЯрдХ scrollToRef React.Component ред


 function Accordion ({ marketName, children, index }) { const positionReference = React.createRef(); const defaultOpenAccordions = index >= config.defaultOpenAccordions; return ( <Accordion defaultOpen={!defaultOpenAccordions} headerName={headerName} onChange={(open) => { publishAccordeonAnalytics(open, marketName); if (defaultOpenAccordions) { scrollToRef(positionReference); } }} id={marketName} > {children} {defaultOpenAccordions && <div data-testId="referenced-div" ref={positionReference} />} </Accordion> ); } 

рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдиреАрдЪреЗ рдЧрд┐рд░ рдЧрдП ... рдкрд░реАрдХреНрд╖рдг ' scrollToRef ' рдЬрд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ scrollToRef рдлрд╝рдВрдХреНрд╢рди рдЕрдм рдПрдХ рдШрдЯрдХ рдирд┐рдЬреА рд╡рд┐рдзрд┐ рдирд╣реАрдВ рд╣реИред рдпрд╣реА рдмрд╛рдд ' ' рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде рднреА рд╣реЛрдЧреА, рд▓реЗрдХрд┐рди рдпрд╣ рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдПрдХ рдЖрдпрд╛рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдм рдпрд╣ рдкрд╛рд░рд┐рдд рд╣реЛ рдЧрдпрд╛ рд╣реИред


рдПрдХ рдЕрдЪреНрдЫрд╛ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдореЗрд░реЗ рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░рддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛:


  1. рдПрдХ рдЕрдХреЙрд░реНрдбрд┐рдпрди рдорд┐рд▓рд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡рд╣ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ рдЬреЛ рдЙрд╕реЗ рдЪрд╛рд╣рд┐рдП
  2. рдЗрд╕реЗ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭреМрддреЗ рдХреЗ рдирд╛рдо рдкрд░ рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛ рдЧрдпрд╛
  3. рдореИрдВ рдЗрдлрдирд╛ рдкрдврд╝рддрд╛ рд╣реВрдВ
  4. рдмрдВрдж рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╕рдордЭреМрддрд╛


рдореБрдЭреЗ рдорд╣рд╕реВрд╕ рд╣реБрдЖ рдХрд┐ рдЙрд╕реЗ рдЗрд╕ рдмрд╛рдд рдХреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдореЗрд░реЗ рдШрдЯрдХ рдХреЛ рдХреНрдпрд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╡рд╣ рдЗрд╕ рдкрд░ рдХреНрдпрд╛ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реА рддрд░рд╣ред рдЗрд╕ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реБрдП, рдореБрдЭреЗ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:


 import '@testing-library/jest-dom/extend-expect'; import { render, fireEvent, screen } from '@testing-library/react'; jest.mock('@myProject/analyticsHelpers'); describe('', () => { test('  ', () => { const child = <div></div>; //  тДЦ 10   const { getByText } = render( <Accordion headerName="  10" index={9}> {child} </Accordion> ); //   fireEvent.click(getByText(/  10/i)); expect(publishAccordeonAnalytics).toHaveBeenCalled(); expect(screen.queryByText('')).toBeInTheDocument(); expect(screen.getByTestId('referenced-div')).toBeInTheDocument(); //   fireEvent.click(getByText(/  10/i)); expect(publishAccordeonAnalytics).toHaveBeenCalled(); }); }); 

рдЕрдм рдореИрдВрдиреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд┐рдпрд╛ рд╣реИред рдореБрдЭреЗ 10 рд╡рд╛рдБ рдЕрдХреЙрд░реНрдбрд┐рдпрди рдорд┐рд▓рд╛, рдЙрд╕ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд┐рдпрд╛, рд╕рд╛рдордЧреНрд░реА рдкрдврд╝реА, рдЙрд╕реЗ рдмрдВрдж рдХрд┐рдпрд╛ - рдпрд╣ рдмрд╛рдд рд╣реИ!


рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдиреЗрддреНрд░рд╣реАрди рдмрд╣реБрдд рдХреНрд▓реАрдирд░ рд╣реИ, рд░рд┐рдлреИрдХреНрдЯрд┐рдВрдЧ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдореЗрд░реЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рд▓рд┐рдЦрдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдерд╛ред


рдЗрд╕ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рдореВрд▓ рдПрдВрдЬрд╛рдЗрдо instance() , state() , find('ComponentName') рдФрд░ рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдмрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХреЛрдб рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВред


рдирдП рдЯреЗрд╕реНрдЯ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛


Source: https://habr.com/ru/post/hi485438/


All Articles