Skip to content

Instantly share code, notes, and snippets.

@yeromin
Last active July 4, 2020 21:07
Show Gist options
  • Save yeromin/ed47a7899ad52eb807036b40e831a168 to your computer and use it in GitHub Desktop.
Save yeromin/ed47a7899ad52eb807036b40e831a168 to your computer and use it in GitHub Desktop.

REACT hints

router

<BrowserRouter>
  <Switch>
    <Route exact path="/">
      <Main
        mockData={this.props.mockData}
        onClickOfferCardTitle={this.handleOfferCardTitleClick}
      />
    </Route>

    <Route exact path="/dev-property/:title" >
      {/* component={Property} */}
      {(props) => <Property {...props}/>}
    </Route>

  </Switch>

</BrowserRouter>

destructurization

Inside function-component:

const Property = (props) => {

  const propertyID = props.match.params.id;
  const arr = props.mockData.offerCard;
  
  return (
    <React.Fragment>
      <div>{propertyID.type}</div>
    </React.Fragment>
  )
}

may be:

const Property = ({match: {params: {id: propertyID}}, mockData: {offerCard: arr}}) => {

  const currentItem = arr.find(({id}) => id === propertyID);
  const {id, badge, type, bedrooms, people, hostBadge, ownerAvatar, images, rating, price, pricePer, title, facilities} = currentItem;

  return (
    <React.Fragment>
    ...
      <div>{type}</div>
    ...
    </React.Fragment>
  )
}

patterns

1. children props:

(props.children - тут children - служебное неизменяемое название)

<Title>
  <h1>title</h1>
</Title>

export default (props) => {
  return (
    <title>
      {props.children}
    </title>
  )
}

2. render props

<Title render={() => (<h1>header</h1>)} />

export default (props) => {
  return (
    <title>
      {props.render()}
    </title>
  )
}

conditional render props:

<Header render={
  (isMobile) => (
    isMobile
      ? <h1>Для котиков</h1>
      : <h1>Товары для котиков</h1>
  )
} />

// componet: 
const isMobile = true; // Какое-то жуткое вычисление мобильных на JavaScript
export default (props) => (
  <header>
    {props.render(isMobile)}
  </header>
);

3. proxy component

(когда нужно сильно изменить компонент, полностью изменить его детей и т.д.)

//APP
export default () => {
  return (
    <React.Fragment>
      <Header>
        <h1>Товары для котиков</h1>
      </Header>
      <Main>
        <ul className="products">
          {
            products.map((product) => (
              <li key={product.id}>
                <ProductNew className="product--in-list" product={product} />
              </li>
            ))
          }
        </ul>
      </Main>
    </React.Fragment>
  );
};

//PRODUCT
export default ({className, product}) => (
  <article className={`product ${className}`}>
    {product.type && <mark>{product.type}</mark>}
    <h3><a href="#">{product.title || `Артикул ${product.id}`}</a></h3>
    <p>{product.price}</p>
  </article>
);

//PRODUCT-NEW
import Product from "./product.jsx";

export default (props) => {
  // 1. конкатинируем все классы
  const className = `product--new ${props.className || ``}`;

  // 2.удаляем тот класс, который пришел из оригинальных пропсов
  const restProps = Object.assign({}, props)
  delete restProps.className;

  // 3.юзаем (передаем) className где хранятся все сконкатенированные классы
  return (
    <Product className={className} {...restProps} />
  );
};


/*
  Если бы в проекте был транспилятор (Babel),
  можно было бы писать так:
  const {className, ...restProps} = props;
  <Product className={`product--new ${className}`} {...restProps} />
*/

4. container component

(когда в контейнере собираем логику по отрисовке дочерних компонентов)

//APP
export default () => {
  return (
    <React.Fragment>
      <Header>
        <h1>Товары для котиков</h1>
      </Header>
      <Main>
        <ProductList products={products} />
      </Main>
    </React.Fragment>
  );
};

//PRODUCT-LIST - C O N T A I N E R 
import Product from "./product.jsx";
import ProductNew from "./product-new.jsx";
import ProductSale from "./product-sale.jsx";
import {Type} from "../data.js";

export default ({products}) => {
  const getComponentByType = (type, product) => {
    switch (type) {
      case Type.SALE:
        return;
      case Type.NEW:
        return;
      default:
        return;
    }
  };

  return (
    <ul className="products">
      {
        products.map((product) => (
          <li key={product.id}>
            <Product product={product} />
          </li>
        ))
      }
    </ul>
  );
};

5. Hight Order Component

(если нужно кастомизировать компонент, допустим, рендерить что-то в зависимости от 2х и больше пропсов) (если мы хотим расшарить между компонентами логику - это HOC) (обычно, называется с приставкой with-)

//APP

const App = () => {
  return (
    <form className="form">
      <p>
        <Toggle>Включи меня</Toggle>
      </p>
      <p>
        <InputHelp placeholder="Заполни меня" />
      </p>
    </form>
  );
}

ReactDOM.render(<App />, document.getElementById(`root`));

//INPUT
import {withActiveFlag} from "./withActiveFlag.jsx";

const InputHelp = (props) => {
  const {isActive, onActiveChange, ...restProps} = props;

  return (
    <React.Fragment>
      <input
        type="text"
        onFocus={onActiveChange}
        onBlur={onActiveChange}
        {...restProps}
      />
      {isActive && (
        <span className="help">
          Подсказка по заполнению
        </span>
      )}
    </React.Fragment>
  );
}

// THIS IS HOW WE USE HOC
// JUST PASS INTO THE HOC DESIRED FUNCTION
export default withActiveFlag(InputHelp); 


//withActiveFlag - H O C 
export const withActiveFlag = Component => props => {
  const [isActive, setActive] = React.useState(false);
  
  const handleActiveChange = () => setActive(!isActive);

  return (
    <Component
      {...props}
      isActive={isActive}
      onActiveChange={handleActiveChange}
    />
  );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment