宣告 UserHeader component
src/components/UserHeader.js
class UserHeader extends Component {

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

    render() {
        const user = this.props.users.find(user => user.id === this.props.userId);
        console.log("user", user);

        return <div>{user?.name}</div>
    }
}

const mapStateToProps = (state) => {
    return {users: state.users}
}

export default connect(mapStateToProps, {fetchUser})(UserHeader)

加到 PttPosts.js
src/components/PttPosts.js
import React, {Component} from "react";
import {connect} from 'react-redux'
import {fetchPosts, selectPttPost} from "../actions";
import UserHeader from "./UserHeader";


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

    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, { fetchPosts, selectPttPost })(PttPosts)

定義 action creator,放入 action
src/actions/index.js
export const fetchUser = (userId) => async dispatch => {
    const response = await jsonPlaceholder.get(`/users/${userId}`)

    dispatch({type:'FETCH_USER', payload: response.data})
}

新增 usersReducer 並加到 combineReducer
export const usersReducer = (state = [], action) => {
    if (action.type === 'FETCH_USER') {
        return [...state, action.payload]; // add payload to existing state
    }

    return state;
}

export default combineReducers({
    selectedPttPost: selectedPttPostReducer,
    fetchPosts: fetchPostReducer,
    users: usersReducer
})

顯示頁面

注意
  1. 把 action payload 放到 state 陣列裡,會導致大量陣列元素在不同程式碼之間傳遞
  2. 如果不把 action payload 放到 state 陣列,UserHeader 會一直顯示最新的結果