Reputation: 194
I have a component that I am trying to access data from my redux store. I am able, through my dev tools, to see that the data is populating into the redux store. However when I try to console.log that data to see the data before I implement it into my component I am getting undefined.
Here is my react component.
import React, { Fragment, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Table } from 'react-bootstrap';
import Moment from 'react-moment';
import Button from '../components/Button';
import ActivitySummary from '../components/ActivitySummary';
import { projectsInfoDetails } from '../actions/projectInfoActions';
import { projectContacts } from '../actions/projectContactActions';
import SectionHeader from '../components/SectionHeader';
import Loader from '../components/Loader';
import Message from '../components/Message';
const ProjectScreen = ({ match }) => {
const dispatch = useDispatch();
const projectInfoDetails = useSelector(state => state.projectInfoDetails);
const { loading, error, projects } = projectInfoDetails;
const contactDetails = useSelector(state => state.contactDetails);
const { projectContactDetails } = contactDetails;
useEffect(() => {
dispatch(projectsInfoDetails(match.params.id));
dispatch(projectContacts(match.params.id));
}, [dispatch, match]);
console.log(projectContactDetails);
return (
<Fragment>
<div>
<SectionHeader sectionName='Project' />
<Button buttonName='Edit Project' />
</div>
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<div style={{ backgroundColor: '#F8F8F8' }}>
<Table className='borderless'>
<tbody>
<tr>
<td>
<strong>Name: </strong>
{projects.name}
</td>
<td>
<strong>Status: </strong>
{projects.status}
</td>
</tr>
<tr>
<td>
<strong>State: </strong>
{projects.state}
</td>
<td>
<strong>County: </strong>
{projects.county}
</td>
</tr>
<tr>
<td>
<strong>Congressional District: </strong>
{projects.district}
</td>
<td>
<strong>Type: </strong>
{projects.type}
</td>
</tr>
<tr>
<td>
<strong>Funding Source: </strong>
<br />
{`${projects.fundingSource} ${projects.fundingSourceName}`}
</td>
<td>
<strong>Funding Source Goal: </strong>
<br />
{projects.fundingSourceGoal}
</td>
<td>
<strong>Start Date: </strong>
<br />
<Moment format='MM/DD/YYYY'>{projects.startDate}</Moment>
</td>
<td>
<strong>End Date: </strong>
<br />
{projects.endDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>{projects.endDate}</Moment>
)}
</td>
<td>
<strong>Funding Percent: </strong>
<br />
{projects.fundingPercent}
</td>
</tr>
<tr>
<td>
<strong>Contact: </strong>
{projects.contact}
</td>
</tr>
<tr>
<td>
<strong>Start Date: </strong>
<Moment format='MM/DD/YYYY'>
{projects.projectStartDate}
</Moment>
</td>
<td>
<strong>End Date: </strong>
{projects.projectEndDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>
{projects.projectEndDate}
</Moment>
)}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Goals and Objectives: </strong>
{projects.goalsAndObjectives}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Success Description: </strong>
{projects.successDescription}
</td>
</tr>
<tr>
<td>
<strong>Accountable Staff</strong>
{projects.accountableStaff &&
projects.accountableStaff.map(data => (
<tr key={data._id}>
{data.lastName}, {data.firstName}
</tr>
))}
</td>
</tr>
<tr>
<td>
<strong>Project ID: </strong>
{projects.projectId}
</td>
</tr>
</tbody>
</Table>
</div>
)}
<ActivitySummary />
</Fragment>
);
};
export default ProjectScreen;
Here is my reducer:
import {
PROJECT_CONTACT_REQUEST,
PROJECT_CONTACT_SUCCESS,
PROJECT_CONTACT_FAIL
} from '../constants/projectConstants';
export const projectContactReducer = (
state = { projectContact: [] },
action
) => {
switch (action.type) {
case PROJECT_CONTACT_REQUEST:
return { loading: true, projectContact: [] };
case PROJECT_CONTACT_SUCCESS:
return { loading: false, projectContact: action.payload };
case PROJECT_CONTACT_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
};
and finally my action call:
import axios from 'axios';
import {
PROJECT_CONTACT_REQUEST,
PROJECT_CONTACT_SUCCESS,
PROJECT_CONTACT_FAIL
} from '../constants/projectConstants';
export const projectContacts = id => async dispatch => {
try {
dispatch({ type: PROJECT_CONTACT_REQUEST });
const { data } = await axios.get(`/api/projects/${id}/projectscontact`);
dispatch({
type: PROJECT_CONTACT_SUCCESS,
payload: data
});
} catch (error) {
dispatch({
type: PROJECT_CONTACT_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message
});
}
};
Here is what the response from the server looks like in my dev tools:
my guess is that it has something to do with the data not populating before the console.log, but cannot seem to access the data.
Thanks
TL
my combine reducers file:
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import { projectDetailsReducer } from './reducers/projectReducer';
import { pageReducer } from './reducers/pageReducer';
import { projectInfoReducer } from './reducers/projectInfoReducer';
import { fundingSourceReducer } from './reducers/fundingSourcesReducer';
import { fundSourceReducer } from './reducers/fundingSourceReducer';
import { contactsReducer } from './reducers/contactsReducer';
import { contactReducer } from './reducers/contactReducer';
import { projectContactReducer } from './reducers/projectContactReducer';
const reducer = combineReducers({
projectDetails: projectDetailsReducer,
projectInfoDetails: projectInfoReducer,
pageDetails: pageReducer,
fundingSourceDetails: fundingSourceReducer,
fundSourceDetails: fundSourceReducer,
contactsDetails: contactsReducer,
contactDetails: contactReducer,
projectContactDetails: projectContactReducer
});
const initialState = {};
const middleware = [thunk];
const store = createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
Upvotes: 0
Views: 83
Reputation: 1222
You get projectContactDetails
wrong. There is projectContact
not projectContactDetails
in state of the projectContactReducer
reducer so you should get that like:
const contactDetails = useSelector(state => state.projectContactDetails);
const { projectContact } = contactDetails;
Upvotes: 1