Questions about selecting data from NgRx store

For point number 2

I would suggest adding another boolean hasSearched: boolean in your reducer, and remove hasSearched from the component. Subscribe to hasSearched using a selector in your component. When the user enters the component first time it should be undefined. From that, you can display your message

   <p *ngIf="(hasSearched | async) === undefined">
       Please enter a search keyword to start searching for books.
   </p>

When the user clicks on the button you will dispatch your action BooksActions.loadBooksFromApi. In the same action/reducer convert the field hasSearchedto false when the API call is in progress, This false flag will stop these two messages from being displayed:

<h5 *ngIf="(hasSearched | async)">No. of books: {{ books.length }}</h5>

<p *ngIf="(hasSearched | async) && !books.length">No books found</p>

Make it true to when it has been completed. As a reference, Your state and reducer will look like this then.

    export interface BooksState {
       books: any;
       hasSearched: boolean;
    }

    export const initialState: BooksState = {
       books: undefined,
       hasSearched: undefined
    };

The reducer will cases would look something like this.

    case BooksActionsTypes.loadBooksFromApi:
      return {
        ...state,
        hasSearched: false
     };

    case BooksActionsTypes.loadBooksFromApiSuccessful:
      return {
        ...state,
        books: action.payload.books
        hasSearched: true
     };

For point number 4

What you are thinking Is correct in my understanding, clearing the state by dispatching an action on ngOnDestroy(). It is the same way I use, to clear states when I want to have a fresh state on my next visit to the same component. It would be something similar to what I have written below

    case BooksActionsTypes.ClearState:
      return {
        ...state,
        books: undefined
        hasSearched: undefined
       };