Yêu cầu thg 2 20, 2020 3:08 SA 494 0 4
  • 494 0 4
0

REACTJS , Làm sao để trigger một Function từ một component khác không có quan hệ gì

Chia sẻ
  • 494 0 4

Chào các bạn, mình có vấn đề này nhờ mn giúp đỡ.

Tại comp PostForm, mình muốn khi tạo một bài viết mới xong sẽ gọi lại hàm getPostList bên component PostList thì làm thế nào ạ. https://codesandbox.io/s/determined-meadow-epy4p

Cám ơn mn đã đọc bài viết của m !

4 CÂU TRẢ LỜI


Đã trả lời thg 2 20, 2020 6:51 SA
+3

Ý tưởng ở đây đơn giản là gọi lại hàm thì bạn có thể tạo ra 1 listener ở bên PostList và trigger nó ở bên PostForm. Có rất nhiều thư viên hỗ trợ làm trò này: https://github.com/facebook/emitter https://nodejs.org/api/events.html

Chia sẻ
Đã trả lời thg 2 20, 2020 7:15 SA
+3

trong sandbox của bạn thì 2 component đang ko có liên hệ gì, về lý thuyết là không thể nhé, tuy nhiên mình giả sử bạn sẽ render 2 component PostForm và PostList trong component App thì sẽ giải quyết như sau:

  • Như mình nói thì 2 Component sẽ cần có mối liên hệ, ở đây 2 component đều được render trong component App, thì đó chính là mối liên hệ, function getPostList thay vì đặt trong component PostList thì đặt ở trong component App, và truyền function đó xuống cả 2 component PostForm và PostList (data nhận được là postList cũng truyền xuống component PostList dưới dạng props) --> đây là flow hoạt động của component trong React, khi 2 component cần giao tiếp với nhau, thì chúng giao tiếp thông qua Component chung (component cha hoặc lớn hơn cha như ông, cụ,... :v )
  • khi app lớn lên việc quản lý sẽ khó hơn nên bạn sẽ nên biết thêm các công cụ quản lý state như redux hay mobx hoặc dùng Context API của React (cái này thì khó dùng hơn 2 thằng kia nhưng ko cần cài thêm lib), cho phép bạn gọi trực tiếp function mà không cần truyền props qua nhiều lớp component. Anw, với bài toán hiện tại của bạn thì cứ làm như trên để hiểu đã nhé.
Chia sẻ
Avatar Hoang vn @wiliamfeng
thg 2 20, 2020 8:19 SA
Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 8:21 SA

Vâng cám ơn bạn, cách thứ nhất bạn nói là cái đầu tiên mình nghĩ đến nhưng vì trong dự án thực tế, component chung của của mình xử lý nhiều quá, nên mình muốn tách bớt phần xử lý này sang component con để code clear hơn. Thế nên m mới muốn hỏi xem có cách nào vẹn cả đôi đường không

thg 2 21, 2020 8:45 SA

bạn đang muốn reuse lại hàm getPostList nhỉ, có vài cách tùy nhu cầu thực tế?

  1. chuyển hết logic của nó vào 1 cái saga, 2 component kia chỉ dispatch action (thông dụng nhất nhưng phải lắp lắm toy: redux, redux-saga)
  2. chuyển logic vào 1 hàm đặt ở component cha (đơn giản nhất nhưng 2 component sẽ bị ràng buộc về quan hệ)
  3. viết custom hook (chỉ áp dụng cho functional component)
  4. viết HOC (ngày xưa chưa có hook thì người ta hay dùng HOC)

nhưng trong ví dụ của bạn thì dùng cách nào cũng sida cả, vì vấn đề chính là: state của bạn đang để ở local component => bạn nên quay lại fix design như a @cuong_nguyen đề xuất thay vì quấn theo chiều gió :v, tức:

  1. gói 2 thằng vào component cha
  2. đẩy state và logic getPostList lên component cha
  3. viết custom hook để lược bỏ logic của getPostList khỏi component cha

=> vừa đơn giản, vừa gọn, vẹn đôi đường (t hiểu đây là dự án chơi chơi thôi nhé chứ thực tế phải lắp redux vào r xài cách 1)

Đã trả lời thg 2 20, 2020 3:20 SA
+1

Theo mình hiểu thì ý tưởng của bạn là sau khi tạo mới sẽ gọi lại hàm getPostList để đẩy bài viết đó vào state, hiện ra view.

Để làm được điều này thì có 2 cách:

  1. Bạn có thể tìm hiểu thêm về Redux Saga, ở đây chúng ta sẽ có một store lưu trữ dữ liệu chung, mỗi khi bạn postForm mới xong, bạn đẩy post đó vào store, ở phía postList bạn chỉ cần sử dụng các post từ store này, mỗi khi có post mới được đẩy vào store thì bên postList sẽ tự động hiển thị

  2. Nếu bạn không biết về Redux Saga thì có thể tạo ra một Component chung cho 2 component PostForm và PostList, hàm getPostList bạn đặt trong component cha này. Sau đó bạn truyền hàm này vào component PostForm dưới dạng tham số, cứ mỗi khi có post mới được cập nhật bằng PostForm, bạn gọi đến getPostList.

Ở bên PostList, bạn truyền cho nó tham số post được lấy từ state của Component chung

// Component chung

state = {
    posts: ""
  };

  componentDidMount() {
    this.getPostList();
  }

  getPostList = () => {
    const response = fetch("GET", "blog/post-list");
    if (response.stattus === 200) {
      this.setState({
        posts: response.data
      });
    }
  };

render {
    const { posts } = this.state;
   return ( <div>
            <PostForm getPostList={this.getPostList} />
            <PostList posts={posts} />
    </div> )
}

Chia sẻ
Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 3:40 SA

Hàm call api getPostList bắt buộc phải đặt trong component chung, để có thể truyền hàm này thành pops xuống cho comp createPost để nó có thể gọi lại được đúng không bạn. Vẫn phải làm vậy thôi chứ ko có cách khác đúng ko ạ

thg 2 20, 2020 3:53 SA

@thanh_tuan bởi vì bạn không sử dụng redux store mà đang dùng local state nên bạn cần đặt hàm getPostList ở component chung để hàm này sau khi nhận data từ API có thể set được state trên component chung này

Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 4:04 SA

@hongquanfit nếu mình dùng Redux thì có cách nào làm ngắn gọn không ạ, có phải xử lý trong component chung nữa ko bạn. Bạn support thêm m dduwockj ko ?

Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 4:08 SA

Mình nghĩ dùng Redux chỉ giúp m share được dữ liệu trong store giữa các component thôi chứ ở đây mình đang cần share function giữa các component mà phải không bạn ?

thg 2 20, 2020 6:00 SA

@thanh_tuan vấn đề là thế này bạn ơi. Khi bạn lưu dữ liệu tập trung, thì bạn có thể truy cập và thay đổi dữ liệu đó ở bất cứ component nào, tức là function getPostList kia của bạn có đặt ở component nào thì cũng đều có thể cập nhật lại list Post và tương tự, mọi component đều có thể lấy ra list Post, chứ nếu dùng local state, bạn lưu Post ở component nào thì chỉ có thể đặt function trong component đó thôi

Còn cách share thì như ở trên kìa bạn :v không phải tự dưng ng ta làm ra Redux cho vui thôi đâu

Avatar Hoang vn @wiliamfeng
thg 2 20, 2020 8:20 SA
Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 8:22 SA

@hongquanfit thank b !

Đã trả lời thg 2 20, 2020 3:24 SA
+1

Bạn thử tìm hiểu về redux xem sao. Nó sẽ có 1 store để lưu dữ liệu và tất cả các component của bạn đều có thể lấy được dữ liệu từ store đó

Chia sẻ
Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 3:41 SA

cams ơn bạn, mình nghĩ có dùng redux đi chăng nữa thì cũng vẫn phải gọi lại API getPostList để cập nhật list post chứ nhỉ.

Hay nó có cách giải quyết hay hơn với bài toán này của m

Avatar Dương Mạnh Hoàng @duong.manh.hoang
thg 2 20, 2020 6:01 SA

@thanh_tuan đúng bạn, mình sẽ gọi lại cái API lấy ra list posts. Theo mình đọc code bạn share thì function getListPost của bạn cũng đang là việc bạn gọi cái API đó mà

Avatar Hoang vn @wiliamfeng
thg 2 20, 2020 8:19 SA
Avatar Anh Tran @thanh_tuan
thg 2 20, 2020 8:22 SA

thank b !

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí