#redux #next.js #server-side-rendering #redux-thunk #next-redux-wrapper
Вопрос:
Я хочу передать реквизиты getServerSideProps компонента страницы дочернему компоненту, но я получаю TypeError: Cannot read property 'title' of undefined
store.js
import { createStore, applyMiddleware } from 'redux';
import { createWrapper } from 'next-redux-wrapper';
import thunkMiddleware from 'redux-thunk';
import rootReducers from './reducers/index';
const bindMiddleware = (middleware) => {
if (process.env.NODE_ENV !== 'production') {
const { composeWithDevTools } = require('redux-devtools-extension');
return composeWithDevTools(applyMiddleware(...middleware));
}
return applyMiddleware(...middleware);
};
const initStore = () => {
return createStore(rootReducers, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore);
действие с промежуточным программным обеспечением redux-thunk
import { API_URL } from "../../../config";
import { ErrorAction, getPosteAction } from "../posts/actionCreator";
export const getPoste = () => {
return async (dispatch) => {
//dispatch(getPosteAction())
function onSuccess(success) {
dispatch(getPosteAction(success));
return success;
}
function onError(error) {
dispatch(ErrorAction());
return error;
}
try {
const data = await fetch(`${API_URL}posts`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
const success = await data.json();
console.log("posst is", success);
return onSuccess(success);
} catch (error) {
return onError(error);
}
};
};
редуктор
import { ADD_POST, GET_POST } from '../constants/posts';
const initialState = {
loading: false,
error: null,
};
const posteReducer = (state = initialState, action) => {
// const { Poste } = state
switch (action.type) {
case ADD_POST:
// return Object.assign({}, state, {
// poste: state.Poste.concat(action.payload),
// })
// console.log("cocococo:", action.payload)
return {
...state,
loading: true,
Poste: action.payload,
};
case GET_POST:
return {
...state,
loading: true,
...action.payload,
};
case 'ERROR':
return {
...state,
loading: false,
Poste: [],
error: action.msg,
};
default:
return state;
}
};
export default posteReducer;
in this working for me but my problem in getServerSideProps i dont know how to get data from action and passing it to props :/
//import { sortedPosts } from '../index';
import Accordion from '../../../../components/homeContent/Accordion';
import { getPoste } from "../../../../redux/actions/posts/actionsThunk-api";
import { wrapper } from "../../../../redux/store";
// export default async (req, res) => {
// const resp = await fetch(`${API_URL}posts`);
// const posts = await resp.json();
// res.status(200).json(posts);
// };
export const getServerSideProps = wrapper.getServerSideProps(
({ store, req, ress }) => {
const posts = await store.dispatch(getPoste());
console.log("data server:", posts);
return {
props: {
posts
}
}
}
);
export default ({ posts }) => {
<>
{posts?.map((post) => (
<Accordion key={post._id} {...post} />
))}
</>;
};
problem exactly in this file if calling to posts.title
here is:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Accordion from "@material-ui/core/Accordion";
import AccordionDetails from "@material-ui/core/AccordionDetails";
import AccordionSummary from "@material-ui/core/AccordionSummary";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import Avatar from "@material-ui/core/Avatar";
import Chip from "@material-ui/core/Chip";
import Box from "@material-ui/core/Box";
import Grid from "@material-ui/core/Grid";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
//import { useDispatch } from "react-redux";
//import { getPoste } from "../../redux/actions/posts/actionsThunk-api";
const useStyles = makeStyles((theme) => ({
heading: {
fontSize: theme.typography.pxToRem(15),
flexBasis: "33.33%",
flexShrink: 0,
},
secondaryHeading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
root: {
width: "100%",
padding: "5px",
},
chip: {
height: "100%",
borderRadius: "25px",
backgroundColor: theme.palette.primary.main,
},
gris: {
backgroundColor: "#232323",
color: "#ffffff",
borderRadius: "10px",
},
rotat: {
transform: "rotate(30deg)",
},
derotat: {
transform: "rotate(-30deg)",
},
}));
export default function TheAccordion({ post }) {
//const dispatch = useDispatch();
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
const handleChange = (panel) => (event, isExpanded) => {
setExpanded(isExpanded ? panel : false);
};
// React.useEffect(() => {
// dispatch(getPoste());
// }, [dispatch]);
return (
<div className={classes.root}>
<Accordion
expanded={expanded === "panel1"}
onChange={handleChange("panel1")}
className={expanded ? classes.gris : ""}
>
<AccordionSummary
expandIcon={
<ExpandMoreIcon className={expanded ? classes.gris : ""} />
}
aria-controls="panel1bh-content"
id="panel1bh-header"
>
{!expanded ? (
<>
<Chip
className={classes.chip}
avatar={
<Avatar
style={{
height: "50px",
width: "50px",
marginTop: "3px",
marginBottom: "3px",
}}
></Avatar>
}
label="user 77"
/>
<Typography noWrap>{post.title}</Typography>
<Button
small="true"
color="primary"
startIcon={<PlayArrowIcon className={classes.rotat} />}
>
25
</Button>
<Button
small="true"
color="secondary"
startIcon={<PlayArrowIcon className={classes.derotat} />}
>
13
</Button>
<Typography style={{ textAlign: "center" }}>1h</Typography>
</>
) : (
<div style={{ width: "100%" }}>
<Box display="flex" alignItems="flex-start">
<Box>
<Avatar
style={{
height: "50px",
width: "50px",
margin: "0px",
marginLeft: "5px",
}}
></Avatar>
</Box>
<Box flexGrow={1} display="flex">
<Box flexGrow={1}>
<Typography
variant="h6"
color="primary"
style={{ paddingLeft: "10px" }}
>
Carlos Wisozk
</Typography>
</Box>
<Box>
<Typography style={{ paddingTop: "10px" }}>
1h ago
</Typography>
</Box>
</Box>
</Box>
</div>
)}
</AccordionSummary>
<AccordionDetails>
<Grid container className={classes.root}>
<Grid item xs={11} style={{ paddingLeft: "20px" }}>
<Typography
variant="h5"
style={{
paddingLeft: "8px",
paddingNottom: "2px",
marginTop: "-5px",
}}
>
hello world
</Typography>
<Typography style={{ paddingLeft: "5px" }}>
accordetailsdion details accordion detailsvvv accordion details
accordion details accordion details accordion accordetailsdion
details accordion detailsvvv accordion details accordion details
accordion details accordion... <span color="primary">more</span>
</Typography>
</Grid>
<Grid
item
container
xs={1}
justify="flex-end"
alignItems="flex-end"
>
<Typography color="primary">answer</Typography>
</Grid>
</Grid>
</AccordionDetails>
</Accordion>
</div>
);
}