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
Related
I'm working on a project with pokeapi graphql and I made a infinite scroll component that loads more pokemon when you scroll the page. I wanted to have the first 48 pokemons pre loaded with static generation.
So I have my index page the following code:
const Home = ({ fallback }): JSX.Element => {
return (
<div>
<SWRConfig value={fallback}>
<PokemonList />
</SWRConfig>
</div>
);
};
export const getStaticProps: GetStaticProps = async () => {
const url =
'species: pokemon_v2_pokemonspecies(order_by: {id: asc}, limit: 24, offset: 0)';
const pokemonList = await getPokemonListData({
url,
});
return {
props: {
fallback: {
'species: pokemon_v2_pokemonspecies(order_by: {id: asc}, limit: 24, offset: 0)':
pokemonList,
},
},
revalidate: 60 * 60 * 24, // 24 hours
};
};
And I use this custom hook for the data:
import getPokemonListData from '#requests/getPokemonListData';
import useSWRInfinite from 'swr/infinite';
interface IUsePokemonListParams {
limit?: number;
}
interface IUsePokemonListReponse {
pokemonList: IBasicPokemonInfo[][];
isLoading: boolean;
size: number;
setSize: (
size: number | ((_size: number) => number),
) => Promise<IBasicPokemonInfo[][]>;
}
export default function usePokemonList({
limit,
}: IUsePokemonListParams): IUsePokemonListReponse {
const getKey = (pageIndex, previousPageData) => {
if (previousPageData && !previousPageData.length) return null; // reached the end
return `species: pokemon_v2_pokemonspecies(order_by: {id: asc}, limit: ${limit}, offset: ${
pageIndex * limit
})`;
};
const { data, error, size, setSize } = useSWRInfinite(getKey, url =>
getPokemonListData({ url }),
);
return {
pokemonList: data,
isLoading: !error && !data,
size,
setSize,
};
}
on my list component I use the custom hook and list the data in another component:
const PokemonList = (): JSX.Element => {
const loader = useRef(null);
const { pokemonList, setSize } = usePokemonList({ limit: 24 });
useController({ loader, setSize }); // this is my infinite scroll logic, I set the size when I reach the page limit
useEffect(() => {
document.body.className = 'initial';
}, []);
return (
<>
<ol className={styles.cardContainer}>
<>
{pokemonList.map((list, index) => (
<Fragment key={index}>
{list.map(pokemon => (
<li key={pokemon.id}>
<Pokemon
id={pokemon.id}
name={pokemon.name}
types={pokemon.types}
image={pokemon.image}
/>
</li>
))}
</Fragment>
))}
</>
</ol>
<div ref={loader} />
</>
);
};
However, when I call the custom hook on my list component, for some reason the data returned from the hook, in this case the "pokemonList", is undefined and the request has to be made again. Is there something that I'm missing?
You have a mistake in your SWRConfig. Instead of <SWRConfig value={fallback}> you should have <SWRConfig value={{fallback}}>
I am using react redux-thunk. I have a set of users data that I get from an API and this is the schema:
.
I've connected the "active" property with the checked attribute of a Switch MUI button, so naturally when calling the API I have some users with their switch button already on "true". What I am trying to do is to just make the switch functional, and just be able to click it and change its state, not necessarily doing anything with that.
Here's my toggleType.js:
export const TOGGLE = "TOGGLE";
Here's my toggleAction.js:
import { TOGGLE } from "./toggleType";
const statusToggleAction = () => {
return {
type: TOGGLE,
};
};
export const statusToggle = () => {
return (dispatch) => {
dispatch(statusToggleAction);
};
};
Here's my toggleReducer.js:
import { TOGGLE } from "./toggleType";
const initialState = {
status: false,
};
const toggleReducer = (state = initialState, action) => {
switch (action.type) {
case TOGGLE:
status: true;
default:
return state;
}
};
export default toggleReducer;
Everything is under my userContainer.js, like that:
function UserContainer({ userData, fetchUsers }) {
useEffect(() => {
fetchUsers();
}, []);
return userData.loading ? (
<h2>Loading</h2>
) : userData.error ? (
<h2>{userData.error}</h2>
) : (
<Container maxWidth="lg" style={{ flexGrow: 1, height: "100%" }}>
<h2>User List</h2>
<div>
{userData &&
userData.users &&
userData.users.map((user) => (
<div key={user.id}>
<p>{user.name}</p>
<Switch checked={user.active} onChange={statusToggle()} />
</div>
))}
</div>
</Container>
);
}
const mapStateToProps = (state) => {
return { userData: state.user, statusToggle: state.status };
};
const mapDispatchToProps = (dispatch) => {
return {
fetchUsers: () => dispatch(fetchUsers()),
statusToggle: () => dispatch(statusToggle()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(UserContainer);
This is the error I am getting whenever I am clicking one of those switches:
Any ideas are welcome, I "learned" redux like 3 days ago!
toggleReducer function in toggleReducer.js, replace status: true; with return { status: true }.
Just return action in statusToggle function in toggleAction.js without dispatch as following.
export const statusToggle = () => {
return statusToggleAction();
};
Or just call statusToggleAction directly in userContainer.js as following.
export const statusToggle = () => {
return (dispatch) => {
dispatch(statusToggleAction());
};
};
i use antd vue model to create a confirm modal,and use createVNode for my content
const modalRef = Modal.confirm({
content: createVNode(CategoryTreeAddModal),
centered: true,
icon: undefined,
onCancel: (event) => {
console.log(CategoryTreeAddModal)
// modalRef.destroy();
},
onOk: (event) => {
console.log(CategoryTreeAddModal)
// modalRef.destroy();
}
})
and this is my content code
<template>
<a-form ref="formRef" :model="formState" :rules="rules" class="login-form">
<a-form-item ref="name" name="name">
<a-input v-model:value="formState.name" placeholder="请输入名称" />
</a-form-item>
</a-form>
</template>
it just warning me Failed to resolve component:a-input a-form-item a-form, how to resolve,ijust wanna use this way to create my confirm modal
You can try this
const instalce = getCurrentInstance()
const vnode = createVNode(CategoryTreeAddModal)
vnode.appContext = instance.appContext
const modalRef = Modal.confirm({
content: vnode,
centered: true,
icon: undefined,
onCancel: (event) => {
console.log(CategoryTreeAddModal)
// modalRef.destroy();
},
onOk: (event) => {
console.log(CategoryTreeAddModal)
// modalRef.destroy();
}
})
How to declare an array on a state variable
Im using react native expo and firebase all is up to date
export default class Profile extends Component {
state = {
ageRangeValues: this.props.user.ageRange,
distanceValue: [this.props.user.distance],
}
render() {
const {
ageRangeValues,
distanceValue,
} = this.state;
return (
<View>
<Slider
min={5}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({ distanceValue: val })}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<Slider
min={18}
max={70}
values={ageRangeValues}
onValuesChange={val => this.setState({ ageRangeValues: val })}
onValuesChangeFinish={val => this.updateUser('ageRange', val)}
/>
</View>) }
I expect this to work fine but the ageRangeValue is undefined but the distanceValue in defined don't know why may be is because ageRangeValue takes ageRange and its an Array. If I declare areRangeValue: [19, 20], everything works, but if I left it the way it is all my values are undefined
and here is my preload
const firebaseConfig = {
apiKey: 'XXXXXXXXX',
databaseURL: 'XXXXX',
storageBucket: 'XXXXX',
};
firebase.initializeApp(firebaseConfig);
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
width: null,
height: null,
resizeMode: 'contain',
},
});
export default class Preload extends Component {
constructor() {
super();
this.loadApp();
// SVGAnimatedLengthList.loadApp();
}
authenticate = (token) => {
const provider = firebase.auth.FacebookAuthProvider
const credential = provider.credential(token);
return firebase.auth().signInWithCredential(credential);
};
_goHome = (user) => {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Home', params: { user } })],
});
this.props.navigation.dispatch(resetAction);
};
loadApp = async () => {
//firebase.auth().signOut();
firebase.auth().onAuthStateChanged((auth) => {
if (auth) {
this.firebaseRef = firebase.database().ref('users');
this.firebaseRef.child(auth.uid).on('value', (snap) => {
const user = firebase.auth().currentUser;
if (user != null) {
this.firebaseRef.child(auth.uid).off('value');
this._goHome(user);
}
});
} else {
this.setState({ showSpinner: false });
this.props.navigation.navigate('Login');
}
});
}
render() {
return (
<ImageBackground source={require('./images/fondo.png')} style={styles.container}>
<ActivityIndicator />
</ImageBackground>
);
}
}
Try it with constructor
export default class Profile extends Component {
constructor(){
super();
this.state = {
ageRangeValues: this.props.user.ageRange,
distanceValue: [this.props.user.distance],
};
}
render() {
const { ageRangeValues, distanceValue } = this.state;
return (
<View>
<Slider
min={5}
max={100}
values={distanceValue}
onValuesChange={val => this.setState({ distanceValue: val })}
onValuesChangeFinish={val => this.updateUser('distance', val[0])}
/>
<Slider
min={18}
max={70}
values={ageRangeValues}
onValuesChange={val => this.setState({ ageRangeValues: val })}
onValuesChangeFinish={val => this.updateUser('ageRange', val)}
/>
</View>
);
}
Vencovsky was right on the previews page that pass the data
loadApp = async () => {
//firebase.auth().signOut();
firebase.auth().onAuthStateChanged((auth) => {
if (auth) {
this.firebaseRef = firebase.database().ref('users');
this.firebaseRef.child(auth.uid).on('value', (snap) => {
const user = firebase.auth().currentUser;
if (user != null) {
this.firebaseRef.child(auth.uid).off('value');
this._goHome(user);
}
});
} else {
this.setState({ showSpinner: false });
this.props.navigation.navigate('Login');
}
});
}
Changing const user = firebase.auth().currentUser; to const user = snap.val();
made the trick
I'm following egghead.io Redux course by Dan.
However I've no idea why my todo app is not working. It doesn't output any error and any warning, just doesn't work.
Can you please give me some hint.
This is my jsbin.
https://jsbin.com/cozecip/33/edit?js,output
const todo = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return {
id: action.id,
text: action.text,
completed: false
};
case 'TOGGLE_TODO':
if (state.id !== action.id) {
return state;
}
return {
id: state.id,
text: state.text,
completed: !state.completed
};
default:
return state;
}
};
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
todo(undefined, action)
];
case 'TOGGLE_TODO':
return state.map(t =>
todo(t, action)
);
default:
return state;
}
};
const visibilityFilter = (state = 'SHOW_ALL', action) =>
{
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter;
default:
return state;
}
};
const { combineReducers } = Redux;
const todoApp = combineReducers({
todos,
visibilityFilter
});
const { createStore } = Redux;
const store = createStore(todoApp);
const { Component } = React;
const FilterLink = ({
filter,
currentFilter,
children,
onClick
}) => {
if (filter === currentFilter){
return <span>{children}</span>
}
return (
<a href="#" onClick ={onClick}>{children}</a>
);
};
const Todo = ({
onClick,
completed,
text
}) => (
<li
onClick={onClick}
style={{
textDecoration:
completed ?
'line-through' :
'none'
}}
>
{text}
</li>
);
const TodoList = ({
todos,
onTodoClick
}) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
const AddTodo = ({
onAddClick
}) => {
let input;
return (
<div>
<input ref={node => {
input = node;
}} />
<button onClick={() => {
onAddClick(input.value)
input.value = '';
}}>
Add Todo
</button>
</div>
);
}
const Footer = ({
visibilityFilter,
onFilterClick
}) => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
currentFilter={visibilityFilter}
onClick={onFilterClick}>
All
</FilterLink>
{' '}
<FilterLink
filter='SHOW_ACTIVE'
currentFilter={visibilityFilter}
onClick={onFilterClick}>
Active
</FilterLink>
{' '}
<FilterLink
filter='SHOW_COMPLETED'
currentFilter={visibilityFilter}
onClick={onFilterClick}>
Completed
</FilterLink>
</p>
)
const getVisibleTodos = (todos, filter) => {
switch(filter){
case 'SHOW_ALL':
return todos;
case 'SHOW_COMPLETED':
return todos.filter(t => t.completed);
case 'SHOW_ACTIVE':
return todos.filter(t => !t.completed);
default:
return todos;
}
}
let nextTodoId = 0;
const TodoApp = ({
todos,
visibilityFilter
}) => {
return (
<div>
<AddTodo
onAddClick={
text =>
store.dispatch({
type: 'ADD_TODO',
text: this.input.value,
id: nextTodoId++
})
}
/>
<TodoList
todos={
getVisibleTodos(
todos,
visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
<Footer
visibilityFilter={visibilityFilter}
onFilterClick={filter =>
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter
})
}
/>
</div>
);
}
const render = () => {
ReactDOM.render(
// Render the TodoApp Component to the <div> with id 'root'
<TodoApp
{...store.getState()}
/>,
document.getElementById('root')
);
};
store.subscribe(render);
render();
Make sure you have added the correct ID in index.js
it should look like this.
document.getElementById('your div id from index.html should go here')