0

I am trying to develop a simple image list component with react-redux stack. This are my actions, reducers, saga and component root definitions -

// Actions 

export const getImageListData = () => ({
    type: IMAGE_LIST_GET_DATA
});

export const getImageListDataSuccess = (data) => {
    console.log("ACTION::SUCCESS", data);
    return ({
        type: IMAGE_LIST_GET_DATA_SUCCESS,
        payload: data
    });
};

// Reducers

export default (state = INIT_STATE, action) => {
    console.log("REDUCER::", state, action);
    switch (action.type) {

        case IMAGE_LIST_GET_DATA: return { ...state, isLoading: true };
        case IMAGE_LIST_GET_DATA_SUCCESS: return { ...state, items: action.payload.data, isLoading: false };

        default: return { ...state };
    }
}

// Sagas

import imagesData from "Data/images.json";

function* loadImages() {
    try {
        const response = yield call(loadImagesAsync);
        console.log("SAGA:: ", response);
        yield put(getImageListDataSuccess(response));
    } catch (error) {
        console.log(error);
    }
}

const loadImagesAsync = async () => {
        const contacts = imagesData;
        return await new Promise((success, fail) => {
            setTimeout(() => {
                success(contacts);
            }, 2000);
        }).then(response => response).catch(error => error);

};

export function* watchGetImages() {
    console.log("ACTION::INIT", IMAGE_LIST_GET_DATA);
    yield takeEvery(IMAGE_LIST_GET_DATA, loadImages);
}

export default function* rootSaga() {
    yield all([
        fork(watchGetImages)
    ]);
}

Now in the component I am calling - getImageListData action

and with this mapStateToProps and connect provider -

const mapStateToProps = ({ ImageList }) => {
    const {items} = ImageList;
    return {items};
};

export default connect(
    mapStateToProps,
    {
        getImageListData
    }
)(ImageListLayout);

I am mapping the image list response to the component props. My component definition is as follows -

class ImageListLayout extends Component {
    constructor(props) {
        super(props);

        this.state = {
            displayMode: "imagelist",
            pageSizes: [8, 12, 24],
            selectedPageSize: 8,
            categories:  [
                {label:'Cakes',value:'Cakes',key:0},
                {label:'Cupcakes',value:'Cupcakes',key:1},
                {label:'Desserts',value:'Desserts',key:2},
            ],
            orderOptions:[
                {column: "title",label: "Product Name"},
                {column: "category",label: "Category"},
                {column: "status",label: "Status"}
            ],
            selectedOrderOption:  {column: "title",label: "Product Name"},
            dropdownSplitOpen: false,
            modalOpen: false,
            currentPage: 1,
            items: [],
            totalItemCount: 0,
            totalPage: 1,
            search: "",
            selectedItems: [],
            lastChecked: null,
            displayOptionsIsOpen: false,
            isLoading:false
        };
    }
    componentDidMount() {
        this.dataListRender();
    }

    dataListRender() {
        this.props.getImageListData();
    }

    render() {
        ...
    }
}

Now in my component I am able to correctly access this.props.items obtained from reducer with action IMAGE_LIST_GET_DATA_SUCCESS, but I also want to update some of the state variables like isLoading, currentPage, totalItemCount, totalPage and since these belong to this component itself and not their parents I do not want to map them to the props but want to update the state of the component and trigger a re-render.

Can someone please tell me what should I be doing to fix this or am i missing anything else here ?

Harshit Laddha
  • 2,044
  • 8
  • 34
  • 64

1 Answers1

0

In your current setup I see no reason for you to have isLoading, etc. in the state. You should just map it to props:

const mapStateToProps = ({ ImageList, isLoading }) => {
    const {items} = ImageList;
    return {items, isLoading};
};

I don't get why you say "and since these belong to this component itself and not their parents I do not want to map them to the props but want to update the state of the component and trigger a re-render." what do parents have to do with anything here?

Mykybo
  • 1,429
  • 1
  • 12
  • 24
  • Reading https://stackoverflow.com/questions/27991366/what-is-the-difference-between-state-and-props-in-react this made me think I am not supposed to use props for properties that belong to the component and not needed by parents as it is waste to pass them down to component from top level container because the intermediary components do not need to use these. Hence I thought I need to save these variables in component state itself. In case if I wanted to update the state from the reducer why are the changes made to the state in the reducer not reflecting in the render method ? – Harshit Laddha Jun 09 '19 at 10:36