I'm new reactjs
I'm trying to save data that I got from server like object(array) but I can't.
at render() function, what should I do to save data, I don't wanna display, just save to users (array) or something? I think that I should use "map" but I don't know how to do.
Next, I wanna save users to model.data like this. help me.
Since you just started using react, try using React Hooks instead of class style components. It's the recommended way.
If you just want to store the data without displaying anything you need somekind of a encapsulated/shared state. For example redux or context can help you with that. Since context is in-built and easier to use, here is an example:
First create a context
users-context.js
import React from "react";
export const UsersContext= React.createContext();
Now create a custom hook to store your state.
useUsers.js
import React, {useState, useEffect} from "react";
export const useUsers = () => {
const [users, setUsers] = useState([]);
const getUsers = () =>{
//your fetch
}
useEffect(()=>{ //equivalent to componentDidMount
getUsers();
}, [])
return {users, setUsers}
}
Then provide the context so every component in your app has access to that context.
App.jsx
import {UsersContext} from "./UsersContext";
const App = () => {
const contextValue = useUsers();
return (
<div className={'App'}>
<UsersContext.Provider value={contextValue}>
<Main/>
</UsersContext.Provider>
</div>
);
};
export default App;
If you want to use the state in a component, e.g. a profile page do this:
profile-page.jsx
import React, {useContext} from "react";
import {UsersContext} from "./UsersContext";
const ProfilePage = () => {
const {users} = useContext(UsersContext);
// now you can use it like
console.log(users)
return (...)
}
import { UsersContext } from './Components/usersData/users-context';
const getUsers = () => {
const {users} = UsersContext(UsersContext);
console.log(users);
return users;
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data:[]
}
data.push(getUsers);`
}
}
Related
Here I am getting my data from child component and trying to add it into existing array and also I am trying to display it in console using map but the moment I try to to do so I get nothing in console:
import "./App.css";
import Home from "./Components/Home";
import {useState} from 'react';
let App = () => {
let DataList = ["Apple","Banana"];
const newList = (data)=>{
DataList = [...DataList,data];
}
return (
<div>
<Home newList = {newList}/>
{ DataList.map((val)=>(
console.log(val)
))
}
</div>
)
};
export default App;
You need to use React hooks to make it work, then only your component will rerender
import "./App.css";
import Home from "./Components/Home";
import {useState} from 'react';
let App = () => {
const [DataList, setDataList] = useState(["Apple","Banana"]);
const newList = (data)=>{
let temp = [...DataList,data];
setDataList(temp);
}
return (
<div>
<Home newList = {newList}/>
{ DataList.map((val)=>(
console.log(val)
))
}
</div>
)
};
export default App;
You imported this for a reason, use it:
import {useState} from 'react';
React won't detect changes to any random variable you declare. So there's no reason for it to re-render the component in the code you have.
State values are fundamental to React. It's how you persist data across renders, and it's how React knows to re-render any given component. Store your data in state:
const [dataList, setDataList] = useState(["Apple","Banana"]);
And use that setter function to update the state:
const newList = (data)=>{
setDataList([...dataList, data]);
};
When React sees that state was updated, it will queue a re-render of the component (in this case re-invoking the App function internally to the framework) so the new state can be used.
What I am trying to do is to add components iteratively from the last dynamically added component.
|dynamically added component| ----on click----> |added new component| ---on click--> | added another component|
import React, { useState } from 'react';
import Product from '../../Product';
import Project from '../../Project';
const NewProject = () => {
const [productList, setProductList] = useState([]);
const addProduct = () => {
setProductList([...productList, <Product addProduct={addProduct} key={productList.length}></Product>]);
};
return <React.Fragment>
<Project addProduct={addProduct}>
</Project>
{productList}
</React.Fragment>
}
export default NewProject;
Basically, I'm passing addProduct const to the Product component and it executes the addProduct function again. I see addProduct is triggered but I don't see component came. I think I'm mixing some states there.
Adding Product component from Project component props works fine by the way. But I want to do the same with added product components.
I don't know the exact problem but the way I use it is a little bit different instead of saving Product Component to the list, I only save the product data then I create a another function to render them into components and then pass it in return like below:
import React, { useState } from 'react';
import Product from '../../Product';
import Project from '../../Project';
const NewProject = () => {
const [products, setProducts] = useState([{}]);
const addProduct = () => {
setProducts([...products, {}]);
};
const renderProducts = () => products.map((_, i) => <Product addProduct={addProduct}/>)
return <>{renderProducts()}</>;
};
export default NewProject;
I'm new to React and I am trying to utilize notistack for ReactJs and I would like to display the notification by calling a helper function but I'm not quite sure how to do that. Here is the standard code required to use the component:
App component:
import { SnackbarProvider } from 'notistack';
<SnackbarProvider maxSnack={3}>
<App />
</SnackbarProvider>
Component that displays the notification:
import { withSnackbar } from 'notistack';
class MyComponent extends Component {
handleNetworkRequest = () => {
fetchSomeData()
.then(() => this.props.enqueueSnackbar('Successfully fetched the data.'))
.catch(() => this.props.enqueueSnackbar('Failed fetching data.'));
};
render(){
//...
};
};
export default withSnackbar(MyComponent);
I would like to place the enqueueSnackbar('my notification message') inside a class or some kind of helper function so that I can call the helper function from anywhere in the react app to display a message without having to wrap the export of a component with withSnackbar(MyComponent);. How can this be done?
I would achieve this via Context API like so:
create a context object which holds the enqueueSnackbar function
Then pass it from the uppermost App comp or any other parent comp
Access it anywhere inside any child component and invoke it as needed
Some pseduo code:
// context.js
import React from 'react';
import { useSnackbar } from 'notistack';
const { enqueueSnackbar } = useSnackbar();
const snackbarContext = React.createContext({ enqueueSnackbar });
export default snackbarContext;
Then wrap a parent component in the tree with this context's provider like so:
//parent.js
import SnackbarContext from './context.js'
const App = () => {
return (
<SnackbarContext.Provider>
<SomeParentComponent />
</SnackbarContext.Provider>
);
}
Now it can be used inside a dummy child component like so:
// child.js
import React, {useContext} from 'react'
import SnackbarContext from './context.js'
const DummyChild = ()=>{
const {enqueueSnackbar} = useContext(SnackbarContext);
return (
<div>
<h1>Dummy Component with snackbar invocation</h1>
<button onClick={() => enqueueSnackbar('Wohoooo')}>Show Snackbar</button>
</div>
)
}
Requirement: Show toast on bottom-right corner of the screen on success/error/warning/info.
I can create a toast component and place it on any component where I want to show toasts, but this requires me to put Toast component on every component where I intend to show toasts. Alternatively I can place it on the root component and somehow manage show/hide (maintain state).
What I am wondering is having something similar to following
export class NotificationService {
public notify = ({message, notificationType, timeout=5, autoClose=true, icon=''}: Notification) => {
let show: boolean = true;
let onClose = () => {//do something};
if(autoClose) {
//set timeout
}
return show ? <Toast {...{message, notificationType, onClose, icon}} /> : </>;
}
}
And call this service where ever I need to show toasts.
Would this be the correct way to achieve the required functionality?
You can use AppContext to manage the state of your toast and a hook to trigger it whenever you want.
ToastContext:
import React, { createContext, useContext, useState } from 'react';
export const ToastContext = createContext();
export const useToastState = () => {
return useContext(ToastContext);
};
export default ({ children }) => {
const [toastState, setToastState] = useState(false);
const toastContext = { toastState, setToastState };
return <ToastContext.Provider value={toastContext}>{children}</ToastContext.Provider>;
};
App:
<ToastProvider>
<App/>
<Toast show={toastState}/>
</ToastProvider>
Then anywhere within your app you can do:
import {useToastState} from 'toastContext'
const {toastState, setToastState} = useToastState();
setToastState(!toastState);
Is there a way with new react hooks API to replace a context data fetch?
If you need to load user profile and use it almost everywhere, first you create context and export it:
export const ProfileContext = React.createContext()
Then you import in top component, load data and use provider, like this:
import { ProfileContext } from 'src/shared/ProfileContext'
<ProfileContext.Provider
value={{ profile: profile, reloadProfile: reloadProfile }}
>
<Site />
</ProfileContext.Provider>
Then in some other components you import profile data like this:
import { ProfileContext } from 'src/shared/ProfileContext'
const context = useContext(profile);
But there is a way to export some function with hooks that will have state and share profile with any component that want to get data?
React provides a useContext hook to make use of Context, which has a signature like
const context = useContext(Context);
useContext accepts a context object (the value returned from
React.createContext) and returns the current context value, as given
by the nearest context provider for the given context.
When the provider updates, this Hook will trigger a rerender with the
latest context value.
You can make use of it in your component like
import { ProfileContext } from 'src/shared/ProfileContext'
const Site = () => {
const context = useContext(ProfileContext);
// make use of context values here
}
However if you want to make use of the same context in every component and don't want to import the ProfileContext everywhere you could simply write a custom hook like
import { ProfileContext } from 'src/shared/ProfileContext'
const useProfileContext = () => {
const context = useContext(ProfileContext);
return context;
}
and use it in the components like
const Site = () => {
const context = useProfileContext();
}
However as far a creating a hook which shares data among different component is concerned, Hooks have an instance of the data for them self and don'tshare it unless you make use of Context;
updated:
My previous answer was - You can use custom-hooks with useState for that purpose, but it was wrong because of this fact:
Do two components using the same Hook share state? No. Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.
The right answer how to do it with useContext() provided #ShubhamKhatri
Now i use it like this.
Contexts.js - all context export from one place
export { ClickEventContextProvider,ClickEventContext} from '../contexts/ClickEventContext'
export { PopupContextProvider, PopupContext } from '../contexts/PopupContext'
export { ThemeContextProvider, ThemeContext } from '../contexts/ThemeContext'
export { ProfileContextProvider, ProfileContext } from '../contexts/ProfileContext'
export { WindowSizeContextProvider, WindowSizeContext } from '../contexts/WindowSizeContext'
ClickEventContext.js - one of context examples:
import React, { useState, useEffect } from 'react'
export const ClickEventContext = React.createContext(null)
export const ClickEventContextProvider = props => {
const [clickEvent, clickEventSet] = useState(false)
const handleClick = e => clickEventSet(e)
useEffect(() => {
window.addEventListener('click', handleClick)
return () => {
window.removeEventListener('click', handleClick)
}
}, [])
return (
<ClickEventContext.Provider value={{ clickEvent }}>
{props.children}
</ClickEventContext.Provider>
)
}
import and use:
import React, { useContext, useEffect } from 'react'
import { ClickEventContext } from 'shared/Contexts'
export function Modal({ show, children }) {
const { clickEvent } = useContext(ClickEventContext)
useEffect(() => {
console.log(clickEvent.target)
}, [clickEvent])
return <DivModal show={show}>{children}</DivModal>
}