In the below slice code I am Getting the data from a server using createAsyncThunk. Now I am trying to delete data locally for which I have written a reducer called removeData.
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import axios from "axios";
export const dataTableSlice = createSlice({
name: "dataTable",
initialState: {
isGridData: [],
isLoading: false,
},
reducers: {
removeData: (state, action) => {
const dataSource = [...state.isGridData];
const filteredData = dataSource.filter(
(item) => item.id !== action.payload.id
);
state.isGridData.push(filteredData);
},
},
extraReducers: (builder) => {
builder
.addCase(loadData.pending, (state, action) => {
state.isLoading = true;
})
.addCase(loadData.fulfilled, (state, action) => {
state.isGridData = [...action.payload.data];
state.isLoading = false;
});
},
});
export const loadData = createAsyncThunk("loadData", async () => {
return await axios.get("https://jsonplaceholder.typicode.com/comments");
});
export const { removeData } = dataTableSlice.actions;
export default dataTableSlice.reducer;
Component
import { Table,Popconfirm,Button } from 'antd';
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {loadData,removeData} from '../../features/DataTableState/DataTableSlice';
import "antd/dist/antd.css";
import './DataTable.scss';
const DataTable = () => {
const gridData = useSelector((state) => state.dataTable.isGridData);
const isLoading = useSelector((state) => state.dataTable.isLoading);
const dispatch = useDispatch();
useEffect(() => {
dispatch(loadData());
},[dispatch]);
const inventoryData = gridData.map((item) => ({
...item,
inventory:Math.floor(Math.random() * 6) + 20,
}));
const modifiedData = inventoryData.map(({body,...item}) =>({
...item,
key:item.id,
message:body,
}));
// const handleDelete = (record) =>{
// const dataSource = [...modifiedData];
// const filteredData = dataSource.filter((item) => item.id !== record.id);
// }
const columns = [
{
title:'Id',
dataIndex:'id',
align:'center',
},
{
title:'product',
dataIndex:'name',
align:'center',
editTable:true
},
{
title:'description',
dataIndex:'message',
align:'center',
editTable:true
},
{
title:'inventory',
dataIndex:'inventory',
align:'center',
editTable:false
},
{
title:'Action',
dataIndex:'action',
align:'center',
render: (_,record) =>
modifiedData.length >= 1 ? (
<Popconfirm title="Are you sure?" onConfirm={dispatch(removeData(record))}>
<Button danger type='primary'>Delete</Button>
</Popconfirm>
):null,
},
];
// const data = [
// {
// Id:1,
// product:'gas1',
// description:'18kg',
// inventory:52,
// },
// {
// Id:2,
// product:'gas1',
// description:'18kg',
// inventory:52,
// },
// {
// Id:3,
// product:'gas1',
// description:'18kg',
// inventory:52,
// },
// {
// Id:4,
// product:'gas1',
// description:'18kg',
// inventory:52,
// }
// ]
return (
<div className='data-table'>
<section className='space'></section>
<Table
className='table'
columns={columns}
dataSource={modifiedData}
bordered
loading={isLoading}
style={{flex:2}}/>
</div>
);
}
export default DataTable
Below given are errors in console:
1.serializableStateInvariantMiddleware.ts:195 A non-serializable value was detected in an action, in the path: payload.config.adapter. Value:
Take a look at the logic that dispatched this action: {type: 'loadData/fulfilled', payload: {…}, meta: {…}}
2.Warning: Cannot update a component (DataTable) while rendering a different component (Cell). To locate the bad setState() call inside Cell, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
Related
Could someone direct me into the right direction to find out how to make a axios.put request using reduxtoolkit?
This is my projectsSlice file. The voteProject is where I am having problems. Im just trying hardcoded data for now to get this to work. When I run it without the arrow function it doesnt accept the data and throws an error saying <payloadtoolargeerror: request entity too large at readstream> when I run it as an arrow function as shown here it accepts the projects data but doesnt send the axios.put to db. Any help would be appreciated.
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import axios from '../axios';
import data from './data'
export const getProjects = createAsyncThunk(
"projects/getProjects",
async () => {
const response = await axios.get('/api/v1/works')
return response.data.data
}
)
export const voteProject = (project) => createAsyncThunk(
"projects/voteProject",
async () => {
const response = await axios.put("/api/v1/works/61fe5ee76b924c82c53b7513", {upvote: [1,2]})
console.log("response: _____________________", response)
}
)
// change the state based on the called functio
export const projectsSlice = createSlice({
name: 'projects',
initialState: {
projects: null,
status: null,
},
reducers: {
setUpvote: (state, action) => {
const index = state.projects.findIndex((obj) => obj._id === action.payload.id);
// console.log("Payload: ", action.payload)
// console.log("Index: ", action.payload)
if (action.payload.isDownvote === false) {
return state.projects[index].upvote += 1;
} else if (action.payload.isDownvote === true) {
state.projects[index].upvote += 1;
state.projects[index].downvote -= 1;
}
},
setDownvote: (state, action) => {
const index = state.projects.findIndex((obj) => obj._id === action.payload.id);
if (action.payload.isUpvote === false) {
state.projects[index].downvote += 1;
} else if (action.payload.isUpvote === true) {
state.projects[index].downvote += 1;
state.projects[index].upvote -= 1;
}
},
setSubractVote: (state, action) => {
const index = state.projects.findIndex((obj) => obj._id === action.payload.id);
if (action.payload.voteType === "upvote") {
state.projects[index].upvote -= 1;
} else if (action.payload.voteType === "downvote") {
state.projects[index].downvote -= 1;
}
},
},
extraReducers: builder => {
builder
.addCase(getProjects.pending, (state, action) => {
state.status = 'loading';
})
.addCase(getProjects.fulfilled, (state, action) => {
state.status = 'success';
state.projects = action.payload;
})
.addCase(getProjects.failed, (state, action) => {
state.status = "failed";
})
}
})
//action creators are generated for each case reducer function
export const { setUpvote, setDownvote, setSubractVote } = projectsSlice.actions;
export default projectsSlice.reducer;
Edit your thunk function to
export const voteProject = createAsyncThunk(
'projects/voteProject',
async (data) => {
try {
const response = await axios.put("/api/v1/works/61fe5ee76b924c82c53b7513", data)
return response.data
} catch (err) {
// custom error
}
}
)
export const projectsSlice = createSlice({
name: 'projects',
initialState: {
projects: null,
status: null,
},
extraReducers: (builder) => {
builder.addCase(voteProject.fulfilled, (state, { payload }) => {
// payload is the data response from thunk above
// update your state
})
// add more case
}
})
In your component:
import { voteProject } from './your-slice'
import { useAppDispatch } from '../store'
const dispatch = useAppDispatch()
const onVoting = () => {
dispatch(voteProject({ // your data }))
.unwrap()
.then((originalPromiseResult) => {
// handle result here
})
.catch((rejectedValueOrSerializedError) => {
// handle error here
})
}
Since Redux Toolkit v1.6 has RTK Query integrated in so you can use rtk-query to write date fetching.
i had a game react matching card project to do.the game is consist to choose card in card grid if two carts contents is the same so this two cart will be her matched property true and will be displaying in green color and in the score component will mark 2 matched cards and so on if the card is not matched the cards color contents will be in red and another handler function will come here to make the two cards invisible by change the property of card object visible to false I had release this function it work well in the console but when I try it in the code application it not work at all please help me to fix it there is my code components :
the boardSlice:
const initialState = [
{id: 0, contents: 'Provider', visible: true, matched: true},
{id: 1, contents: 'Provider', visible: true, matched: true},
{id: 2, contents: 'selector', visible: true, matched: true},
{id: 3, contents: 'selector', visible: true, matched: true},
{id: 4, contents: 'useSelector()', visible: true, matched: true},
{id: 5, contents: 'useSelector()', visible: true, matched: true},
{id: 6, contents: 'useDispatch()', visible: true, matched: true},
{id: 7, contents: 'useDispatch()', visible: true, matched: true},
{id: 8, contents: 'Pure Function', visible: true, matched: true},
{id: 9, contents: 'Pure Function', visible: true, matched: true},
{id: 10, contents: 'react-redux', visible: true, matched: true},
{id: 11, contents: 'react-redux', visible: true, matched: true},
];
export const boardReducer = (state = initialState, action) => {
switch (action.type) {
case 'board/setBoard':
let setState = [];
action.payload.forEach((element, index) =>
setState.push({id: index,
contents: element,
visible: false,
matched: false})
);
return setState;
case 'board/flipCard':
let flipState = [...state];
const cardID = action.payload;
flipState[cardID] = {...state[cardID], visible:true}
const [index1, index2] = flipState.filter(card => card.visible).map(card => card.id);
if (index2 !== undefined) {
let card1 = flipState[index1];
let card2 = flipState[index2];
if (card1.contents === card2.contents) {
flipState[index1] = {...card1, visible: false, matched: true};
flipState[index2] = {...card2, visible: false, matched: true};
}
}
return flipState;
case 'board/resetUnmatchedCards':
let newState = [...state];
let [indexa, indexb] = newState.filter(card => card.visible === true && card.matched === false).map(card => card.id);
if (indexb !== undefined) {
let cardA = newState[indexa];
let cardB = newState[indexb];
newState[indexa] = {...cardA, visible: action.payload};
newState[indexb] = {...cardB, visible: action.payload}
}
return newState
case 'board/resetCards':
return state.map(card => ({...card, visible: false}));
default:
return state;
}
}
const wordPairs = [
'Provider', 'Provider',
'selector', 'selector',
'useSelector()', 'useSelector()',
'useDispatch()', 'useDispatch()',
'Pure Function', 'Pure Function',
'react-redux', 'react-redux',
]
const randomWords = () => {
let words = []
let newWordPairs = [...wordPairs]
const reps = newWordPairs.length
for (let i = 0 ; i < reps ; i++) {
const wordIndex = Math.floor(Math.random() * newWordPairs.length);
words.push(newWordPairs[wordIndex])
newWordPairs.splice(wordIndex, 1)
}
return words;
}
// action creators
export const setBoard = () => {
const words = randomWords()
return {
type: 'board/setBoard',
payload: words
}
}
export const flipCard = (id) => {
return {
type: 'board/flipCard',
payload: id
}
}
export const resetCards = (indices) => {
return {
type: 'board/resetCards'
}
};
export const resetUnmatchedCards = () => {
return {
type: 'board/resetUnmatchedCards',
payload: false
}
}
// Add selector export statments below
export const selectBoard = (state) => {
return ( state.board.map(card=>
({
id: card.id,
contents: card.contents
})
))}
export const selectVisibleIDs = state => {
return (
state.board.filter(card => card.visible)
.map(card => card.id)
)
}
export const selectMatchedIDs = state => {
return ( state.board.filter(card => card.matched)
.map(card => card.id));
};
the App component :
import './App.css';
import React from 'react';
import { Score } from './features/score/Score.js';
import { Board } from './features/board/Board.js';
import { useDispatch } from 'react-redux';
import { setBoard, resetCards } from './features/board/boardSlice';
// Add import statements below
const App = () => {
// Add dispatch variable below
const dispatch = useDispatch();
const startGameHandler = () => {
// Add action dispatch below
dispatch(setBoard())
};
const tryAgainHandler = () => {
// Add action dispatch below
dispatch(resetCards())
};
return (
<div className="App">
<Score />
<Board />
<footer className="footer">
<button onClick={startGameHandler} className="start-button">
Start Game
</button>
<button onClick={tryAgainHandler} className="try-new-pair-button">
Try New Pair
</button>
</footer>
</div>
);
};
export default App;
the board component :
import React from 'react';
import { CardRow } from './cardRow/CardRow.js';
// Add import statements below
import { useSelector } from 'react-redux';
import { selectBoard } from './boardSlice';
export const Board = () => {
// Add selected data variable and implement below
const currentBoard = useSelector(selectBoard);
const numberOfCards = currentBoard.length;
const columns = 3;
const rows = Math.floor(numberOfCards / columns);
const getRowCards = (row) => {
const rowCards = [];
for (let j = 0; j < columns; j++) {
const cardIndex = row * columns + j;
// Implement selected data below
rowCards.push(currentBoard[cardIndex]);
}
return rowCards;
};
console.log(currentBoard)
let content = [];
for (let row = 0; row < rows; row++) {
const rowCards = getRowCards(row);
content.push(
<CardRow
key={row}
cards={rowCards}
/>
);
}
return <div className="cards-container">{content}</div>;
};
the cardRow.js:
import React from 'react';
import { Card } from './card/Card.js';
import {selectMatchedIDs } from '../boardSlice'
export const CardRow = ({ cards }) => {
const content = cards.map(card =>
<Card
key={card.id}
id={card.id}
contents={card.contents}
/>)
return <>{content}</>;
};
the Card.js:
import React, {useEffect} from 'react';
// Add import statements below
import { useSelector, useDispatch } from 'react-redux';
import { selectVisibleIDs, flipCard, selectMatchedIDs, } from '../../boardSlice';
import { resetCards, resetUnmatchedCards } from '../../boardSlice'
let cardLogo = "https://static-assets.codecademy.com/Courses/Learn-Redux/matching-game/codecademy_logo.png";
export const Card = ({ id, contents }) => {
// Add selected data and dispatch variables below
const visibleIDs = useSelector(selectVisibleIDs)
const dispatch = useDispatch();
const matchedIDs = useSelector(selectMatchedIDs);
console.log(visibleIDs)
console.log(matchedIDs);
// flip card action
const flipHandler = (id) => {
// Add action dispatch below
dispatch(flipCard(id))
};
const resetHandler = () => {
dispatch(resetUnmatchedCards)
}
let cardStyle = 'resting';
let click = () => flipHandler(id);
let cardText = (
<img src={cardLogo} className="logo-placeholder" alt="Card option" />
);
// 1st if statement
// implement card id array membership check
if (visibleIDs.includes(id) || matchedIDs.includes(id)) {
cardText = contents;
click = () => {};
}
// 2nd if statement
// implement card id array membership check
if (matchedIDs.includes(id)) {
cardStyle = 'matched';
} else {
cardStyle = 'no-match';
}
// 3rd if statement
// implement number of flipped cards check
if (visibleIDs.length === 2) {
if (cardStyle === 'no-match' ) {
click = () => resetHandler();
}
click = ()=> {};
}
return (
<button onClick={click} className={`card ${cardStyle}`}>
{cardText}
</button>
);
};
so the problem is i want to change the click button to an other function to do so when first every card had this object {id:cardId, contents: cardContents, visible: false, matched: false} so first of when the user click two cards by the "FlipCard" action the card.visible become true then if the first card.contents is ht same as the second card.contents so the card.matched property for the two cards will become true so the require thing I want to add another function to reset the two card.visible to false when the first card.contents is not the same as the second card.contents so this is my code of the component Card :
import React, {useEffect} from 'react';
// Add import statements below
import { useSelector, useDispatch } from 'react-redux';
import { selectVisibleIDs, flipCard, selectMatchedIDs, } from '../../boardSlice';
import { resetCards, resetUnmatchedCards } from '../../boardSlice'
let cardLogo = "https://static-assets.codecademy.com/Courses/Learn-Redux/matching-game/codecademy_logo.png";
export const Card = ({ id, contents }) => {
// Add selected data and dispatch variables below
const visibleIDs = useSelector(selectVisibleIDs)
const dispatch = useDispatch();
const matchedIDs = useSelector(selectMatchedIDs);
console.log(matchedIDs);
// flip card action
const flipHandler = (id) => {
// Add action dispatch below
dispatch(flipCard(id))
};
const resetHandler = () => {
dispatch(resetCards)
}
let cardStyle = 'resting';
let click = () => flipHandler(id);
let cardText = (
<img src={cardLogo} className="logo-placeholder" alt="Card option" />
);
// 1st if statement
// implement card id array membership check
if (visibleIDs.includes(id) || matchedIDs.includes(id)) {
cardText = contents;
click = () => {};
}
// 2nd if statement
// implement card id array membership check
if (matchedIDs.includes(id)) {
cardStyle = 'matched';
} else {
cardStyle = 'no-match';
}
console.log(visibleIDs.every(id => matchedIDs.includes(id)))
// 3rd if statement
// implement number of flipped cards check
if (visibleIDs.length === 2 ) {
if (cardStyle === 'no-match' && visibleIDs.every(id => !matchedIDs.includes(id))) {
click = () => resetHandler();
} else {
click = () => {};
}
}
return (
<button onClick={click} className={`card ${cardStyle}`}>
{cardText}
</button>
);
};
i have such problem: I'm making To-Do-List, and now I want to make EditMode for my tasks. But when I try to do it, it returns string not an array, and that's why I have 3 errors (map,some,filter = is not a function). So I don't know how to change state(task) and return changed array.
Some details: I'm using connect to get props.
Component's code
class Item extends React.Component {
state = {
statusChange: false,
task: ''
}
activeStatusChange = () => {
this.setState( {
statusChange: true
}
);
}
deActivateStatusChange = () => {
this.setState( {
statusChange: false
}
);
this.props.editTask(this.state.task)
}
onStatusChange = (e) => {
this.setState({
task: e.currentTarget.value
})
}
render(){
return (
<div className={s.item}>
<span onClick={this.props.editStatus} className={s.statusTask}>
{this.props.status ? <img src="https://img.icons8.com/doodle/48/000000/checkmark.png"/>
: <img src="https://img.icons8.com/emoji/48/000000/red-circle-emoji.png"/>}
</span>
{ this.state.statusChange
? <input onChange={this.onStatusChange} autoFocus={true} onBlur={this.deActivateStatusChange} value={this.state.task} />
: <span className={this.props.status === true ? s.task : s.taskFalse} onClick={this.activeStatusChange}> {this.props.task} </span>}
<span onClick={this.props.deleteTask} className={s.close}><img src="https://img.icons8.com/color/48/000000/close-window.png"/></span>
</div>
)
}
}
export default Item;
Reducer's code
import React from 'react'
import shortid from 'shortid';
const ADD_TASK = 'ADD_TASK'
const EDIT_STATUS = 'EDIT_STATUS'
const TASK_DELETE = 'TASK_DELETE'
const REMOVE_ALL_DONE = 'REMOVE_ALL_DONE'
const REMOVE_ALL_TASKS = 'REMOVE_ALL_TASKS'
const EDIT_TASK = 'EDIT_TASK'
const initialState = {
tasks: []
};
const mainReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TASK: {
return {
...state,
tasks: [{
id: shortid.generate(),
task: action.task,
status: false
}, ...state.tasks]
}
}
case EDIT_STATUS: {
return {
...state,
tasks: state.tasks.map(task => task.id === action.id ? {...task, status: !task.status} : task)
}
}
case TASK_DELETE: {
return {
...state,
tasks: state.tasks.filter(t => t.id !== action.id)
}
}
case REMOVE_ALL_DONE: {
return {
...state,
tasks: state.tasks.filter(t => !t.status)
}
}
case REMOVE_ALL_TASKS: {
return {
...state,
tasks: []
}
}
case EDIT_TASK: {
return {
...state,
tasks: action.task
}
}
default:
return state
}
}
export const addTask = task => ({type: 'ADD_TASK', task});
export const editStatus = id => ({type: 'EDIT_STATUS', id})
export const deleteTask = id => ({type: 'TASK_DELETE', id})
export const removeAllDone = () => ({type:'REMOVE_ALL_DONE'})
export const removeAllTasks = () => ({type: 'REMOVE_ALL_TASKS'})
export const editTask = task => ({type: 'EDIT_TASK', task})
export default mainReducer;
You should create a container that uses the methods mapDispatchToProps so you can use your actions in the component.
https://react-redux.js.org/using-react-redux/connect-mapdispatch
So lets do it. Just create a file that will be your container for that component and put the code like this:
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Item from 'wherever your component is';
import { addTask } from 'wherever your action is';
const mapStateToProps = ({ }) => ({
// Here you can pass the redu state to your component
});
const mapDispatchToProps = (dispatch) => ({
...bindActionCreators({
// Here you pass the action to your component
addTask
}, dispatch)
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Item);
Then when you want to use the Item component import it from the container and it will receive in props both the action and the state that you are passing from the container file.
In you Item component you can use the action like this:
// ITem component
render() {
return (
<button onClick={this.props.addTask} />
)
}
If any doubt just let me know!
This is just a sample code I am trying to control my controlled inputs using Redux, I add the Redux to my React project and add my reducer and action but everything works well except updating my component in one of my actions.
the following code is my Reducer:
import actionTypes from "./actions";
const uniqid = require("uniqid");
const firstID = uniqid();
const initialState = {
cons: [
{
value: "",
id: firstID,
added: false
}
],
pros: [
{
value: "",
id: firstID,
added: false
}
],
num: 0
};
const reducer = (state = initialState, action) => {
const newState = { ...state };
switch (action.type) {
case actionTypes.HANDLEINPUTCHANGE:
// const newState = state;
const changingItem = newState[action.case].find(item => {
return item.id === action.id;
});
const changingItemIndex = newState[action.case].findIndex(item => {
return item.id === action.id;
});
changingItem.value = action.event;
if (
changingItemIndex === newState[action.case].length - 1 &&
!changingItem.added
) {
alert(123);
const newItem = {
id: uniqid(),
value: "",
added: false
};
newState[action.case].push(newItem);
changingItem.added = true;
console.log(newState);
}
newState[action.case][changingItemIndex] = changingItem;
return newState;
case actionTypes.CLICK:
newState.num += 1;
return {
...newState
};
default:
return state;
}
};
export default reducer;
and the following code is my component, unfortunately, the HANDLEINPUTCHANGE action type did not update my component:
import React, { Component } from "react";
import FormElement from "../../base/components/formElement/FormElement";
import actionTypes from "../../base/store/actions";
import { connect } from "react-redux";
import "./style.scss";
class FormGenerator extends Component {
render() {
console.log(this.props);
return (
<ul className="row formGeneratorContainer fdiColumn">
<li onClick={this.props.click}>{this.props.num}</li>
{this.props[this.props.case].map((item, index) => {
return (
<li className="row formGeneratorItem" key={index}>
<div className="bullet d_flex jcCenter aiCenter">1</div>
{/* <FormElement onChange={(e,index,type,)}/> */}
<input
name={item.id}
type="text"
onChange={event =>
this.props.onFieldValueChange(
event.target.value,
index,
this.props.case,
item.id
)
}
/>
</li>
);
})}
</ul>
);
}
}
const mapStateToProps = state => {
return {
cons: state.cons,
pros: state.pros,
num: state.num
};
};
const mapDispachToProps = dispatch => {
return {
onFieldValueChange: (event, index, c, id) =>
dispatch({
event: event,
index: index,
case: c,
id: id,
type: actionTypes.HANDLEINPUTCHANGE
}),
click: () => dispatch({ type: actionTypes.CLICK })
};
};
export default connect(
mapStateToProps,
mapDispachToProps
)(FormGenerator);
You need to set value of your controlled component:
<input
name={item.id}
type="text"
value={item.value}
onChange={event =>
this.props.onFieldValueChange(
event.target.value,
index,
this.props.case,
item.id
)
}
/>
Other problems are in your reducer, you are mutating the redux state with these lines:
newState[action.case].push(newItem);
// ...
newState[action.case][changingItemIndex] = changingItem;
Look at these sections in the redux documentation:
Inserting and Removing Items in Arrays
Updating an Item in an Array
I have a problem with Redux doesn't update the state. Component gets right initial state. Action is dispatched right, data is fetched right and is accesible in action payload inside reducer. Reducer is executing, right case in switch is picked. Just new state doesn't appear in component. I have three others components where it works just fine, only this one cracks.
component
import fetchLinksPage from '../state/links/actions'
...
let Links = ({linksPageLoaded, linksPage, fetchLinksPage}) => {
useEffect( () => {
if(!linksPageLoaded) {
fetchLinksPage()
console.log(linksPage)
}
},[])
return ( ... )
}
const mapStateToProps = ({linksPageReducer}) => {
return linksPageReducer
}
const mapDispatchToProps = dispatch => {
return {
fetchLinksPage: () => dispatch(fetchLinksPage())
}
}
Links = connect(mapStateToProps, mapDispatchToProps)(Links)
actions
// action types
export const GET_LINKS_PAGE = 'GETLINKSPAGE'
export const LINKS_PAGE_LOADED = 'LINKSPAGELOADED'
export const LINKS_PAGE_ERROR = 'LINKSPAGEERROR'
// action creators
export const getLinksPage = () => {
return {
type: GET_LINKS_PAGE
}
}
export const linksPageLoaded = (data) => {
return {
type: LINKS_PAGE_LOADED,
payload: data
}
}
export const linksPageError = (error) => {
return {
type: LINKS_PAGE_ERROR,
payload: error
}
}
const fetchLinksPage = () => {
return dispatch => {
dispatch(getLinksPage())
fetch('http://portfolio.adamzajac.info/_/items/links?fields=*,logo.*.*')
.then(response => response.json())
.then(data => {
dispatch(linksPageLoaded(data.data))
})
.catch( error => {
dispatch(linksPageError(error))
})
}
}
export default fetchLinksPage
reducer
import * as actions from './actions.js'
const linksPageReducer = (state={}, action) => {
switch (action.type) {
case actions.GET_LINKS_PAGE:
return { ...state, linksPageLoading: true }
case actions.LINKS_PAGE_LOADED:
//console.log('update state')
return { ...state, linksPage: action.payload, linksPageLoading: false, linksPageLoaded: true }
case actions.LINKS_PAGE_ERROR:
return { ...state, linksPageError: action.payload, linksPageLoading: false}
default:
return { ...state, linksPageLoading: false, linksPageLoaded: false, linksPage:[], linksPageError:''}
}
}
export default linksPageReducer
store
import aboutPageReducer from './state/about/reducer'
import projectsPageReducer from './state/projects/reducer'
import skillsPageReducer from './state/skills/reducer'
import linksPageReducer from './state/links/reducer'
const rootReducer = combineReducers({
aboutPageReducer,
projectsPageReducer,
skillsPageReducer,
linksPageReducer
})
const store = createStore(
rootReducer,
applyMiddleware(thunk)
)