react-table with localstorage column toggle - redux

{
Header: "Interactions",
Cell: ({ row }) => {
if (store.getState().table.portfolio.includes(row.original)) {
return (
<div>
<button
className="column-interactions"
onClick={() => removeTicker(row.original)}
>
<AiFillHeart />
</button>
</div>
);
} else
return (
<div>
<button
className="column-interactions"
onClick={() => chooseTicker(row.original)}
>
<AiOutlineHeart />
</button>
</div>
);
},
},
At start the column return the else part, as portfolio inside reducer 'table' is empty, it even works fine when i click on the button to store it in redux. Basically it toggles and the data comes and goes from the redux state.
const chooseTicker = (data) => {
if (store.getState().table.portfolio.length <= 5) {
store.dispatch({
type: ADD_PORTFOLIO,
payload: data,
});
let existingPortfolio = JSON.parse(localStorage.getItem("portfolioToken"));
if (existingPortfolio == null) existingPortfolio = [];
existingPortfolio = [...existingPortfolio, data];
localStorage.setItem("portfolioToken", JSON.stringify(existingPortfolio));
}
};
const removeTicker = (data) => {
store.dispatch({
type: REMOVE_PORTFOLIO,
payload: data,
});
let existingPortfolio = JSON.parse(localStorage.getItem("portfolioToken"));
const index = existingPortfolio.findIndex(function (stock) {
return stock.sec_ticker === data.sec_ticker;
});
existingPortfolio.splice(index, 1);
localStorage.setItem("portfolioToken", JSON.stringify(existingPortfolio));
};
But as soon as i refresh the page, the toggle goes back to its default state, which is the else part. But my redux persists the data.
This is how im taking the data from localstorage to redux initial state
const portfolioToken = JSON.parse(localStorage.getItem("portfolioToken"));
let initialState = {};
if (portfolioToken) {
initialState = {
hasPortfolio: !empty(portfolioToken),
portfolio: portfolioToken,
portfolio_like: [],
selected: "all",
rows: [],
weeks: [],
weekSelected: "",
scoreStyle: "scores",
data: {},
isLoading: true,
};
} else {
initialState = {
hasPortfolio: false,
portfolio: [],
portfolio_like: [],
selected: "all",
rows: [],
weeks: [],
weekSelected: "",
scoreStyle: "scores",
data: {},
isLoading: true,
};
}

Related

MUI snackbar div persist on DOM after being closed

I created a global modal with the purpose of only calling it when I need it, but the problem is that the snackbar div persists in the DOM and this causes certain elements to be blocked because they are below this div. Any idea what the problem would be?
My GlobalAlert component:
export function GlobalAlert() {
const {alertState, handleClose} = useAlertContext();
const {open, type, message} = alertState;
function TransitionDown(props: TransitionProps) {
return <Slide {...props} direction="down" />;
}
return (
<Snackbar
key={"top" + "center"}
TransitionComponent={TransitionDown}
anchorOrigin={{vertical: "top", horizontal: "center"}}
autoHideDuration={4000}
disableWindowBlurListener={true}
open={open}
onClose={handleClose}
>
<Alert severity={type} sx={useStyles.alert} variant="filled" onClose={handleClose}>
{message}
</Alert>
</Snackbar>
);
}
Context where I get the info
const AlertContextProvider = (props: any) => {
const [alertState, setAlertState] = React.useState<AlertState>({
open: false,
type: "error",
message: "",
});
const handleClose = React.useCallback((event?: React.SyntheticEvent | Event, reason?: string) => {
if (reason === "clickaway") {
return;
}
setAlertState({
open: false,
type: "error",
message: "",
});
}, []);
const value = React.useMemo(
() => ({
alertState,
setAlertState,
handleClose,
}),
[alertState, handleClose],
);
return <AlertContext.Provider value={value} {...props} />;
};
Bug image

Next js Redux, Objects are not valid as a React child

Error: Objects are not valid as a React child (found: object with keys {_id, name}). If you meant to render a collection of children, use an array instead.
Tried to fix this for days and no result.
i have a model
import mongoose from 'mongoose'
const CategoriesSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
parent: {
type: mongoose.Types.ObjectId,
ref: 'categories'
},
},
{
timestamps: true
})
let Dataset = mongoose.models.categories || mongoose.model('categories', CategoriesSchema)
export default Dataset
and i have getCategories like this
[getCategories ]
const getCategories = async (req, res) => {
try {
const categories = await Categories.find().populate("parent", "name");
res.json({ categories });
}
catch (err)
{
return res.status(500).json({ err: err.message });
}
};
in my Globale state i have
export const DataContext = createContext()
export const DataProvider = ({children}) => {
const initialState = {
notify: {}, auth: {}, cart: [], modal: [], orders: [], users: [], categories: []
}
const [state, dispatch] = useReducer(reducers, initialState)
useEffect(() => {
getData('categories').then(res => {
if(res.err)
return dispatch({type: 'NOTIFY', payload: {error: res.err}})
dispatch({ type: 'ADD_CATEGORIES', payload: res.categories })
})
},[])
return(
<DataContext.Provider value={{state, dispatch}}>
{children}
</DataContext.Provider>
)
}
when i call categories throw:exception
when i change dispatch in Globale state like :
dispatch({ type: 'ADD_CATEGORIES', payload: [] })
i get no elements in array :

Redux immutable pattern

I use react with redux.
Action:
export const updateClicked = (id, section) => {
return {
type: actionTypes.UPDATE_CLICKED,
id,
section
};
};
Please advise the best way to immutable update property in nested array:
Reducer:
const initialState = {
updates: {
html: {
id: 'html',
label: 'HTML',
count: 0,
items: [
{
id: 1,
label: 'Header',
price: 10,
bought: false
},
{
id: 2,
label: 'Sidebar',
price: 50,
bought: false
}
]
}
}
};
My action:
action = {
id: 1,
bought: true
}
I want to update bought property inside items array. I.e.:
const updateClicked= (state, action) => {
const updateSections = state.updates[action.section].items;
const updatedItems = updateSections.map(el => {
if (el.id === action.id && !el.bought) {
el.bought = true;
}
return el;
});
//How to update state???
return {}
};
Will be glad if you explain 2 ways to do this:
With es6 spread operator
With some library (like immutability-helper)
Thanks!
With es6 spread operator:
export default (state = initialState, action) => {
if (action.type !== actionTypes.UPDATE_CLICKED) return state;
return {
...state,
updates: {
...state.updates,
html: {
...state.updates.html,
items: state.updates.html.items.map((item, idx) => idx === action.id
? {...item, bought: item.bought}
: item
)
}
}
}
};

Spinner when loads data from Firebase

I try to create a spinner when loading data from Firebase. I am new to this, so sorry for the basics question. I've come up with this code so far. Declare state , and try to add a conditional statement, but no success:
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
items: [],
loading: true
};
this.itemsRef = this.getRef().child('items');
this._handleResults = this._handleResults.bind(this);
}
listenForItems(itemsRef) {
this.setState({
loading: true
});
itemsRef.on('value', (snap) => {
// get children as an array
var items = [];
snap.forEach((child) => {
items.push({
french: child.val().french,
english: child.val().english,
english_erudite: child.val().english_erudite,
_key: child.key
});
});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(items),
items: items,
loading: false
});
});
}
_renderItem(item) {
const { navigate } = this.props.navigation;
const {loading}= this.state;
if (this.state.loading){
return <Spinner/>
}else{
return(<ListItem item={item} onPress={() =>
navigate('Details', {...item} )} />);
}
}
}

meteor react-autosuggest - Missing class properties transform

I'm using Meteor React and trying to get react-autosuggest working (from the basic usage example https://github.com/moroshko/react-autosuggest
The error I get is Missing class properties transform - it's happening at onChange (right after this.state.
this.state = {
value: '',
suggestions: getSuggestions('')
};
}
onChange = (event, { newValue }) => {
this.setState({
value: newValue
});
};
onSuggestionsUpdateRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value)
});
};
I've looked around to see if I could find a solution, but no luck.
Hopefully someone can shed some light on what's going on.
Using class Example extends React.Component {...} doesn't work with meteor. Try this approach instead:
import React from 'react';
import Autosuggest from 'react-autosuggest';
import AutosuggestHighlight from 'autosuggest-highlight';
Example = React.createClass({
getInitialState() {
return {
value: '',
suggestions: [],
};
},
onChange(event, { newValue }) {
this.setState({
value: newValue,
});
},
onSuggestionsFetchRequested({ value }) {
this.setState({
suggestions: this.getSuggestions(value),
});
},
onSuggestionsClearRequested() {
this.setState({
suggestions: [],
});
},
getSuggestionValue(suggestion) {
return suggestion.name;
},
getSuggestions(value) {
const languages = [
{
name: 'C',
year: 1973,
},
{
name: 'C#',
year: 2001,
},
{
name: 'C++',
year: 1984,
},
{
name: 'Clojure',
year: 2008,
},
{
name: 'Elm',
year: 2013,
},
{
name: 'Go',
year: 2010,
},
];
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
if (inputLength === 0) {
return [];
}
return languages.filter(language =>
language.name.toLowerCase().slice(0, inputLength) === inputValue
);
},
renderSuggestion(suggestion, { query }) {
const suggestionText = `${suggestion.name} (${suggestion.year})`;
const matches = AutosuggestHighlight.match(suggestionText, query);
const parts = AutosuggestHighlight.parse(suggestionText, matches);
return (
<span className="suggestion-content">
<span>
{
parts.map((part, index) => {
const className = part.highlight ? 'highlight' : null;
return (
<span className={className} key={index}>{part.text}</span>
);
})
}
</span>
</span>
);
},
render() {
const { value, suggestions } = this.state;
const inputProps = {
value,
placeholder: 'Enter programming language...',
onChange: this.onChange,
};
return (
<div>
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={this.getSuggestionValue}
renderSuggestion={this.renderSuggestion}
inputProps={inputProps} />
</div>
);
},
});
Then simply use <Example /> to render the autosuggest field.
This was tested with Meteor 1.4.1.1

Resources