redux - redux thunk - prevent duplicated request


=================== Prepare ========================
  • whenever we dispatch a function, redux pick it up and invoke it
export const fetchPostsAndUsers = () => async dispatch => {
    await // need await because invoking an async function and we want to wait until it's done
        dispatch( // dispatch an "async dispatch..." function, so invoke it directly
            fetchPosts() // call export const fetchPosts = ()
                         // and return "async dispatch => { ... }"
        )
}

export const fetchPosts = () => async dispatch => {
    const response = await jsonPlaceholder.get('/posts')

    dispatch({type:'FETCH_POSTS', payload: response.data})
}
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
If a property name is provided for iteratee the created _.property style callback returns the property value of the given element.
Creates a duplicate-free version of an array, using SameValueZero for equality comparisons, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the array.

===================== Need to change =================
  • Remove memoize function
export const fetchUser = (userId) => async dispatch => {
    const response = await jsonPlaceholder.get(`/users/${userId}`)

    dispatch({type:'FETCH_USER', payload: response.data})
}
  • Create fetchPostsAndUsers function
export const fetchPostsAndUsers = () => async (dispatch, getState) => {
    await dispatch (fetchPosts());
    const userIds = _.uniq(_.map(getState().fetchPosts, 'userId'))
    userIds.forEach(id => dispatch(fetchUser(id)))
}
  • Fetch posts and users from PttPosts.js
import React, {Component} from "react";
import {connect} from 'react-redux'
import {fetchPostsAndUsers, selectPttPost} from "../actions";
import UserHeader from "./UserHeader";

class PttPosts extends Component {
    componentDidMount() {
        this.props.fetchPostsAndUsers()
    }

    renderList() {
        if (this.props.postList) {
            return this.props.postList.map((post) => {
                return <div key={post.id}>
                    <div key={post.id}><a onClick={() => this.props.selectPttPost(post)}>Title:{post.title}</a></div>
                    <UserHeader userId={post.userId} />
                </div>
            });
        } else {
            return 'Loading...'
        }
    };

    render() {
        return <div>{this.renderList()}</div>
    }
}

const mapStateToProps = (state) => {
    return {postList: state.fetchPosts};
}

export default connect(mapStateToProps, { fetchPostsAndUsers, selectPttPost })(PttPosts)
  • Don't need fetchUsers from UserHeader.js
import React, {Component} from "react";
import {connect} from 'react-redux'
import {fetchUser} from "../actions";

class UserHeader extends Component {

    componentDidMount() {
        this.props.fetchUser(this.props.userId)
    }

    render() {
        return <div>Author: {this.props.user?.name}</div>
    }
}

const mapStateToProps = (state, props) => {
    return {user: state.users?.find(user => user.id === props.userId)}
}

export default connect(mapStateToProps, {fetchUser})(UserHeader)
  • Duplicated requests disappear


沒有留言:

張貼留言

別名演算法 Alias Method

 題目 每個伺服器支援不同的 TPM (transaction per minute) 當 request 來的時候, 系統需要馬上根據 TPM 的能力隨機找到一個適合的 server. 雖然稱為 "隨機", 但還是需要有 TPM 作為權重. 解法 別名演算法...