tomaytotomato
tomaytotomato

Reputation: 4028

React redux reducer getting data from state?

Trying to mess around with react and redux to fetch a list of files from an API.

When looking in the react dev tools I can see my data there but it is not being rendered.

actions.js

export const requestFiles  = ({
    type: REQUEST_FILES,
});

export const receiveFiles = (json) => ({
    type: RECEIVE_FILES,
    files: json,
    receivedAt: Date.now()
});


export const fetchFiles = (dispatch) => {
    dispatch(requestFiles);
    return fetch('/api/files')
        .then(response => response.json())
        .then(json => dispatch(receiveFiles(json)))
};

The action gets data from JSON

enter image description here

reducer.js

const files = (state = {
    isFetching: false,
    items: []
}, action) => {
    switch (action.type) {
        case REQUEST_FILES:
            return {
                ...state,
                isFetching: true,
            };
        case RECEIVE_FILES:
            return {
                ...state,
                isFetching: false,
                items: action.files,
                lastUpdated: action.receivedAt
            };
        default:
            return state
    }
};

const filesUploaded = (state = { }, action) => {
    switch (action.type) {
        case RECEIVE_FILES:
        case REQUEST_FILES:
            return {
                ...state,
                items: files(state[action], action)
            };
        default:
            return state
    }
};

const rootReducer = combineReducers({
    filesUploaded
});

export default rootReducer

App.js

class App extends Component {
    static propTypes = {
        files: PropTypes.array.isRequired,
        isFetching: PropTypes.bool.isRequired,
        dispatch: PropTypes.func.isRequired
    };

    componentDidMount() {
        const {dispatch} = this.props;
        dispatch(fetchFiles);
    }

    handleChange = nextSubreddit => {
    };

    render() {
        const {files, isFetching} = this.props;
        const isEmpty = files.length === 0;
        console.log(`Files is empty ${isEmpty}`);
        return (
            <div>
                <h1>Uploadr</h1>
                {isEmpty
                    ? (isFetching ? <h2>Loading...</h2> : <h2>No files.</h2>)
                    : <div style={{opacity: isFetching ? 0.5 : 1}}>
                        <Files files={files}/>
                    </div>
                }
            </div>
        )
    }
}

const mapStateToProps = state => {
    const {uploadedFiles} = state;
    const {isFetching, items: files} = uploadedFiles
        || {isFetching: true, items: []};

    console.log(files);

    return {
        files,
        isFetching,
    }
};

enter image description here

The data being received in the action but I am not sure if it is getting stored or if the problem is accessing it from the redux store.

The files property is still zero on the App component as shown in the screenshot above.

Any ideas?

Upvotes: 1

Views: 8915

Answers (2)

tpdietz
tpdietz

Reputation: 1368

Delete your filesUploaded reducer. You don't need it. Instead, just use the files reducer:

const rootReducer = combineReducers({
    files,
}); 

Please note, the slice of state you are interested in will be called files. Change your mapStateToProps function to this:

const mapStateToProps = state => {
    const {isFetching, items: files} = state.files

    console.log(files);

    return {
        files,
        isFetching,
    }
};

You can see here, we grab the files slice of state and pass that into your component.

Upvotes: 1

Charles Stover
Charles Stover

Reputation: 1148

Your filesUploaded reducer does not make any sense. I'm not sure what filesUploaded is even supposed to be doing. Your files reducer looks like a normal reducer. It seems like you could just delete filesUploaded and everything would be fine.

In particular, filesUploaded is calling files(state[action], action). action is an object. What is state[SOME_OBJECT] supposed to be? Because it's being parsed as state['[object Object]'] which is surely undefined and never would become defined.

Your files reducer also has an items parameter that is just never used. A reducer should only have two parameters: state and action. Drop the items parameter.

Your mapStateToProps is looking for state.uploadedFiles, but your reducer is called filesUploaded. It should be state.filesUploaded (or if you replace it with the files reducer, just state.files).

mapStateToProps will not need || {isFetching: true, items: []} since you have an initial state on your files reducer.

Upvotes: 1

Related Questions