Làm chức năng "xem thêm" bằng Reactjs kết hợp với thư viện styled-components

Tổng quan

Chức năng “xem thêm” hay còn có tên gọi tiếng Anh là “read more“. Nó là một chức năng thường được dùng khi tạo trang web dùng để thu gọn hay sổ ra nội dung nhất định trong trang web .Trong bài viết này chúng ta cùng nhau xây dựng chức năng này bằng Reactjs nhé . Trước hết bạn cần học qua về Reactjs và một chút kiến thức về thư viện styled-components.

1. Reactjs là gì?

React Js là một thư viện viết bằng javascript mã nguồn mở và cha đẻ của ReactJS đó chính là một ông lớn với cái tên ai cũng biết đó chính là Facebook. Mục đích của việc tạo ra ReactJS là dùng để xây dựng giao diện người dùng (UI). React được sử dụng rộng rãi và có hệ sinh thái đa dạng phong phú. Reactjs tạo ra những ứng dụng website hấp dẫn với tốc độ nhanh và hiệu quả cao với những dòng code tối thiểu. Và mục đích chủ chốt của ReactJS đó chính là mỗi website khi đã sử dụng ReactJS thì phải chạy thật mượt thật nhanh và có khả năng mở rộng cao và đơn giản thực hiện.

2. Thư viện styled-components là gì?

Nó là một thư viện giúp bạn có thể tổ chức và quản lý code CSS một cách dễ dàng trong các project React. Nó được xây dựng với mục tiêu giữ cho các styles của các components trong React gắn liền với chính các components đó. Nó cung cấp một interface rõ ràng và dễ sử dụng cho cả React và React Native. Nó không chỉ thay đổi việc implement các components trong React mà còn thay đổi cả lối tư duy trong việc xây dựng styles cho các component đó. Với styled-components thay vì sử dụng những selector để làm đẹp cho element chúng ta sẽ định nghĩa những components với style chỉ dành riêng cho bản thân nó. Bạn có thể xem một ví dụ dưới đây .

-Ví dụ bạn có một thành phần HTML như thế này:

<div class="content">

 <span>Học lập trình tại Suntech Việt Nam</span>

</div>


-Và thêm phần css như này

.content {
    background-color: #000;
}
.content > span {
    color: #fff;
}


Đây là một cách tiếp cận truyền thống nhưng nó lại không hoàn toàn phù hợp cho việc viết một project bằng React với một số nhược điểm như sau :

  • Các class, id trong css được dùng chung cho cả trang web dẫn đến việc conflict khi đặt tên cho class, id (có thể được giải quyết bằng naming convention như BEM, hay với Webpack css module)
  • Việc thay đổi style, animation dựa trên đầu vào và trạng thái của element rắc rối và không tự nhiên...vv.
const Wrapper = ({ className }) => (
 <div className={className}>
  <span>Học lập trình tại Suntech Việt Nam</span>
 </div>
);

const StyledWrapper = styled(Wrapper)`
 background-color: #000;

 > span {
  color: #fff;
 }
`;

export default StyledWrapper;

3. Setup và bắt đầu code

-Đầu tiên chúng ta sẽ tạo một file mới mà mình đặt tên là demo-truncate . Mở folder này ra và gõ lệnh

npx create-react-app .


Chúng ta sẽ tạo create-react-app ngay tại chính cái folder demo-truncate( bằng dấu chấm phía sau). Sau khi cài xong và mở nó trên vscode , chúng ta sẽ được thành quả như thế này :


Chúng ta sẽ phải chỉnh lại sourse code . Mà mình sẽ làm theo flow của dự án react mà mình đã làm .Phần code ở file App.js thì mình sẽ thêm một thư viện là react-router-dom . Mình sẽ để router của trang ở file App.js và code logic ở những files khác .Đôi khi bạn sẽ cảm thấy việc sử dụng react-router-dom nó không liên quan và hơi thừa khi làm chức năng này nhưng thôi làm theo mình hi.

yarn add react-router-dom

nếu dùng yarn hoặc

npm install react-router-dom

nếu dùng npm . Cả 2 cách đều ok .

Ở thư mục src các bạn tạo 1 folder tên là routes , bên trong thư mục này tạo thêm 1 file là index.jsx . Tạo thêm 1 folder tên là container , bên trong tạo thêm một folder tên là Home nữa bên trong cũng có 1 file là index.jsx . Tạo thêm 1 folder tên là components , bên trong tạo thêm một folder tên là Truncate , bên trong lại tiếp tục có 1 file là index.jsx . Mình sẽ có cấu trúc như sau:

Trong file index.jsx của routes ta có :

import React from 'react'
import {BrowserRouter as Router ,Switch ,Route} from 'react-router-dom';
import Home from 'container/Home';

export default function MyRouter() {
    return (
        <>
            <Router>
                <Switch>
                    <Route path="/">
                        <Home />
                    </Route>
                </Switch>
            </Router>
        </>
    );
}

Chúng ta sẽ cho component Home của chúng ta ở đây . Trước hết thì ta config một chút về đường dẫn của thư mục nhé . Ở ngoài thư mục src ta tạo thêm một file có tên là jsconfig.json . Chúng ta config nó như sau .

{
    "compilerOptions": {
      "baseUrl""src"
    },
    "include": ["src"]
  }


Ok chúng ta thêm file jsconfig.json mục đích để cho biết thư mục src chính là thư mục gốc của dự án . Có thể thấy khi import một file nào đấy trong dự án ta sẽ không cần những đường dẫn dạng tương đối như ( ../ , ./ , ../../) .Điều này giúp code của chúng ta dễ bảo trì hơn. Ok thì Chúng ta tiếp tục chuyển sang thư mục Truncate để làm việc nào ! . Ta cài thêm thư viện styled-components .

yarn add styled-components

Folder components/Truncate/index.jsx sẽ như sau .

import React from 'react';
import * as S from './styled';
export default function Truncate({line, children}{
  return (
    <>
      <S.Text $line={line}>{children}</S.Text>
    </>
  );
}


import * as S from './styled' . Có nghĩa là import tất cả dưới cái tên là S từ file styled.js .Các bạn có để đặt tên gì cũng được miễn là nó ít code nhất có thể .

Folder components/Truncate/styled.js sẽ như sau .

import styled, {css} from 'styled-components';

export const Text = styled.div`
  ${({$line}) =>
    $line &&
    css`
      -webkit-line-clamp: ${$line} !important;
    `};
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: 3;
  display: -webkit-box;
  -webkit-box-orient: vertical;
`;


Chúng ta sẽ truyền props từ file index.jsx sang styled.js . Và điều chỉnh số dòng thông qua props đến thuộc tính css là -webkit-line-clamp . Mặc định số dòng hiển thị mình cho ở đây là 3 dòng .

Có một mẹo giúp bạn gõ hàm nhanh đó là các bạn gõ rfc hoặc rfce . Enter một cái lập tức nó sẽ cho ra một cấu trúc React function nhanh chóng .



Ok giờ chúng ta sẽ sang thư mục container/Home/index.jsx của chúng ta để import cái Truncate của chúng ta vào nào ! .

import React, {useState} from 'react';
import * as S from './styled';
import Truncate from 'components/Truncate';
export default function Home() {
  const [isShow, setIsShow] = useState(false);

  function handleShow() {
    setIsShow(!isShow);
  }

  return (
    <>
      <S.WrapperTruncate>
        {isShow ? (
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Perferendis, non ipsam! Facere necessitatibus ea vel quidem ratione
            unde suscipit atque amet obcaecati excepturi accusantium magnam
            incidunt quos, error deleniti laboriosam. Lorem, ipsum dolor sit
            amet consectetur adipisicing elit. Perferendis, non ipsam! Facere
            necessitatibus ea vel quidem ratione unde suscipit atque amet
            obcaecati excepturi accusantium magnam incidunt quos, error deleniti
            laboriosam. Lorem, ipsum dolor sit amet consectetur adipisicing
            elit. Perferendis, non ipsam! Facere necessitatibus ea vel quidem
            ratione unde suscipit atque amet obcaecati excepturi accusantium
            magnam incidunt quos, error deleniti laboriosam.
          </p>
        ) : (
          <Truncate line="2">
            Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Perferendis, non ipsam! Facere necessitatibus ea vel quidem ratione
            unde suscipit atque amet obcaecati excepturi accusantium magnam
            incidunt quos, error deleniti laboriosam. Lorem, ipsum dolor sit
            amet consectetur adipisicing elit. Perferendis, non ipsam! Facere
            necessitatibus ea vel quidem ratione unde suscipit atque amet
            obcaecati excepturi accusantium magnam incidunt quos, error deleniti
            laboriosam. Lorem, ipsum dolor sit amet consectetur adipisicing
            elit. Perferendis, non ipsam! Facere necessitatibus ea vel quidem
            ratione unde suscipit atque amet obcaecati excepturi accusantium
            magnam incidunt quos, error deleniti laboriosam.
          </Truncate>
        )}
        {isShow ? (
          <S.Btn onClick={handleShow}>Thu gọn</S.Btn>
        ) : (
          <S.Btn onClick={handleShow}>Xem thêm</S.Btn>
        )}
      </S.WrapperTruncate>
    </>
  );
}


Chúng ta sẽ có một React hook là useState .

Tạo ra 2 state là isShow và setIsShow . Giá trị mặc định ban đầu là false .Khi click thì chúng ta set nó lại khác giá trị của isShow , mà isShow ban đầu cho mặc định là false rồi nên click thì giá trị của nó sẽ bằng true . Nếu các bạn có data từ một api nào đấy thì có thể truyền nó vào thông qua state để cho code nó nhìn nó gọn hơn . Ở đây là mình để dữ liệu cứng vào .

Ở đây mình sử dụng cú pháp rút gọn của câu điều kiện if else. Gọi là Conditional shorthand .

Ơ ! Các bạn có thấy code ở chỗ Button mình làm nó hơi dài quá đúng không ? . Ta hãy refactor lại nào !.

 <S.Btn onClick={handleShow}>{isShow ? 'Thu gọn' : 'Xem thêm  '}</S.Btn>


Yes . Bây giờ chúng ta có được thành quả sau khi refactor lại code .

import React, {useState} from 'react';
import * as S from './styled';
import Truncate from 'components/Truncate';
export default function Home() {
  const [isShow, setIsShow] = useState(false);

  function handleShow() {
    setIsShow(!isShow);
  }

  return (
    <>
      <S.WrapperTruncate>
        {isShow ? (
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Perferendis, non ipsam! Facere necessitatibus ea vel quidem ratione
            unde suscipit atque amet obcaecati excepturi accusantium magnam
            incidunt quos, error deleniti laboriosam. Lorem, ipsum dolor sit
            amet consectetur adipisicing elit. Perferendis, non ipsam! Facere
            necessitatibus ea vel quidem ratione unde suscipit atque amet
            obcaecati excepturi accusantium magnam incidunt quos, error deleniti
            laboriosam. Lorem, ipsum dolor sit amet consectetur adipisicing
            elit. Perferendis, non ipsam! Facere necessitatibus ea vel quidem
            ratione unde suscipit atque amet obcaecati excepturi accusantium
            magnam incidunt quos, error deleniti laboriosam.
          </p>
        ) : (
          <Truncate line="2">
  <p>
              Lorem, ipsum dolor sit amet consectetur adipisicing elit.
              Perferendis, non ipsam! Facere necessitatibus ea vel quidem
              ratione unde suscipit atque amet obcaecati excepturi accusantium
              magnam incidunt quos, error deleniti laboriosam. Lorem, ipsum
              dolor sit amet consectetur adipisicing elit. Perferendis, non
              ipsam! Facere necessitatibus ea vel quidem ratione unde suscipit
              atque amet obcaecati excepturi accusantium magnam incidunt quos,
              error deleniti laboriosam. Lorem, ipsum dolor sit amet consectetur
              adipisicing elit. Perferendis, non ipsam! Facere necessitatibus ea
              vel quidem ratione unde suscipit atque amet obcaecati excepturi
              accusantium magnam incidunt quos, error deleniti laboriosam.
            </p>
            </Truncate>
          )}
          <S.Btn onClick={handleShow}>{isShow ? 'Thu gọn' : 'Xem thêm  '}</S.Btn>
        </S.WrapperTruncate>
      </>
    );
  }

Đến với thư mục container/Home/styled.js của chúng ta .

import styled from 'styled-components';

export const WrapperTruncate = styled.div`
  padding: 30px 20px;
`;
export const Btn = styled.button`
  display: flex;
  algin-items: center;
  justify-content: center;
  padding: 10px 20px;
  outline: none;
  border: none;
  background: blue;
  color: white;
  border-radius: 4px;
  width: 120px;
  cursor: pointer;
  margin: 10px 0px;
`;

Ok chúng ta đã hoàn thành chức năng rồi ! .

4.Lời Kết

Chúng ta đã cùng nhau hoàn thành chức năng vô cùng thú vị này bằng Reactjs và thư viện styled-components rồi . Nó dễ dàng đúng không nào ! . Các bạn có thể vào trang https://truncate.vercel.app/ để xem demo của project . Cảm ơn các bạn đã xem bài viết này và chúc bạn học tốt .

Đinh Sĩ Duyệt
SUNTECH VIỆT NAM   Đăng ký để nhận thông báo mới nhất