error - Error: Must initialize before using hooks - javascript

I have just created a fresh Next app, and after adding line no. 6, I'm getting error. Why?
import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";
import { useConnectWallet, useSetChain, useWallets } from "#web3-onboard/react";
const Home = () => {
const [{ wallet }, connect, disconnect] = useConnectWallet();
const [{ chains, connectedChain, settingChain }, setChain] = useSetChain();
const connectedWallets = useWallets();
return (
<div className={styles.container}>
<Head>
<title>New - emax</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<p>Instantly deploy your Next.js site to a public URL with Vercel.</p>
</main>
</div>
);
};

You need to import and call the init function from #web3-onboard/react before any hooks (eg. useConnectWallet()) can be used.
import {
init,
useConnectWallet,
useSetChain,
useWallets
} from '#web3-onboard/react'
Check here for exact example - https://socket.dev/npm/package/#web3-onboard/react

first call init look like this sample :
import React from 'react'
import {
init,
useConnectWallet,
useSetChain,
useWallets
} from '#web3-onboard/react'
import injectedModule from '#web3-onboard/injected-wallets'
import trezorModule from '#web3-onboard/trezor'
import ledgerModule from '#web3-onboard/ledger'
import walletConnectModule from '#web3-onboard/walletconnect'
import walletLinkModule from '#web3-onboard/walletlink'
import portisModule from '#web3-onboard/portis'
import fortmaticModule from '#web3-onboard/fortmatic'
import torusModule from '#web3-onboard/torus'
import keepkeyModule from '#web3-onboard/keepkey'
const injected = injectedModule()
const walletLink = walletLinkModule()
const walletConnect = walletConnectModule()
const portis = portisModule({
apiKey: 'b2b7586f-2b1e-4c30-a7fb-c2d1533b153b'
})
const fortmatic = fortmaticModule({
apiKey: 'pk_test_886ADCAB855632AA'
})
const torus = torusModule()
const ledger = ledgerModule()
const keepkey = keepkeyModule()
const trezorOptions = {
email: 'test#test.com',
appUrl: 'https://www.blocknative.com'
}
const trezor = trezorModule(trezorOptions)
const web3Onboard = init({
wallets: [
ledger,
trezor,
walletConnect,
keepkey,
walletLink,
injected,
fortmatic,
portis,
torus
],
chains: [
{
id: '0x1',
token: 'ETH',
label: 'Ethereum Mainnet',
rpcUrl: 'https://mainnet.infura.io/v3/ababf9851fd845d0a167825f97eeb12b'
},
{
id: '0x3',
token: 'tROP',
label: 'Ethereum Ropsten Testnet',
rpcUrl: 'https://ropsten.infura.io/v3/ababf9851fd845d0a167825f97eeb12b'
},
{
id: '0x4',
token: 'rETH',
label: 'Ethereum Rinkeby Testnet',
rpcUrl: 'https://rinkeby.infura.io/v3/ababf9851fd845d0a167825f97eeb12b'
},
{
id: '0x89',
token: 'MATIC',
label: 'Matic Mainnet',
rpcUrl: 'https://matic-mainnet.chainstacklabs.com'
}
],
appMetadata: {
name: 'Blocknative',
icon: '<svg><svg/>',
description: 'Demo app for Onboard V2',
recommendedInjectedWallets: [
{ name: 'MetaMask', url: 'https://metamask.io' },
{ name: 'Coinbase', url: 'https://wallet.coinbase.com/' }
]
}
})
function App() {
const [{ wallet, connecting }, connect, disconnect] = useConnectWallet()
const [{ chains, connectedChain, settingChain }, setChain] = useSetChain()
const connectedWallets = useWallets()
return (
<div>
<button onClick={() => connect()}>
{connecting ? 'connecting' : 'connect'}
</button>
{wallet && (
<div>
<label>Switch Chain</label>
{settingChain ? (
<span>Switching chain...</span>
) : (
<select
onChange={({ target: { value } }) =>
console.log('onChange called') || setChain({ chainId: value })
}
value={connectedChain.id}
>
{chains.map(({ id, label }) => {
return <option value={id}>{label}</option>
})}
</select>
)}
<button onClick={() => disconnect(wallet)}>
Disconnect Wallet
</button>
</div>
)}
{connectedWallets.map(({ label, accounts }) => {
return (
<div>
<div>{label}</div>
<div>Accounts: {JSON.stringify(accounts, null, 2)}</div>
</div>
)
})}
</div>
)
}
export default App
see here

Related

display the properties of an object that is itself in an object array

Hello I'm trying to display the content of an object on my html page using react. I managed to access the frontend property that are in my object array. Now when I try to browse each element of my frontend object array and display the id of each element on my page it displays only the first element which is "HTML". But I want to display all the other id on the page. I don't know what is the problem
The external data
const skills = [
{
frontend: [
{
id: 'HTML',
img: './images/skills/html5.svg'
},
{
id: 'CSS',
img: './images/skills/css3.svg'
},
{
id: 'Javascript',
img: './images/skills/javascript.svg'
},
{
id: 'Bootstrap',
img: './images/skills/bootstrap.svg'
},
{
id: 'React JS',
img: './images/skills/react.svg'
},
{
id: 'Flutter',
img: './images/skills/flutter.svg'
},
],
backend: [
{
id: 'PHP',
img: './images/skills/php.svg'
},
{
id: '.NET Core',
img: './images/skills/net-core.svg'
},
{
id: 'Node JS',
img: './images/skills/html5.svg'
},
],
languages: [
{
id: 'Java',
img: './images/skills/java.svg'
},
{
id: 'Python',
img: './images/skills/python.svg'
},
{
id: 'C#',
img: './images/skills/csharp.svg'
},
],
},
];
export default skills;
My home file
import React, { useEffect, useState } from "react";
import "../styles/Home.css";
import Skills from "../data/Skills";
export const Home = () => {
const [skills, setSkills] = useState([]);
useEffect(() => {
setSkills(Skills);
}, []);
const frontend = skills.map((element) => {
return element.frontend;
});
console.log(frontend);
return (
<div className="home">
<div className="skills">
<h1>Skills</h1>
{frontend.map((item, index) => {
console.log(index)
return <ul key={index}>
<li>{item[index].id}</li>
</ul>;
})}
</div>
</div>
);
};
The result is here
If you are already importing data, you don't need to store that into a state,
Try this ,
import React, { useEffect, useState } from "react";
import "./styles.css";
import Skills from "./Skills";
export const Home = () => {
let frontend = [];
Skills.forEach((skill) => {
frontend = [...frontend, ...skill.frontend];
});
return (
<div className="home">
<div className="skills">
<h1>Skills</h1>
{frontend.map((item, index) => {
return (
<ul key={item.id}>
<li>{item.id}</li>
</ul>
);
})}
</div>
</div>
);
};
Try this,
Change data file to
const skills = {
frontend: [...],
backend: [...],
languages: [...],
};
export default skills;
Code
import React, { useEffect, useState } from "react";
import "../styles/Home.css";
import Skills from "../data/Skills";
export const Home = () => {
return (
<div className="home">
<div className="skills">
<h1>Skills</h1>
{Skills.frontend.map(item => <ul key={item.id}>
<li>{item.img}</li>
</ul>}
</div>
</div>
);
};
Or as I understand what you are trying to do, try this
import React, { useEffect, useState } from "react";
import "../styles/Home.css";
import Skills from "../data/Skills";
export const Home = () => {
return (
<div className="home">
<div className="skills">
<h1>Skills</h1>
{Object.keys(Skills).map(skill => <ul key={skill}>
{Skills[skill].map(item => <li key={item.id}>{item.id}</li>)}
</ul>}
</div>
</div>
);
};
Your frontend is a nested array with only one item, so the index is always 0. The following is the fixed version.
import React, { useEffect, useState } from "react";
import "../styles/Home.css";
import Skills from "../data/Skills";
export const Home = () => {
const [skills, setSkills] = useState([]);
useEffect(() => {
setSkills(Skills);
}, []);
const frontend = skills[0].frontend
console.log(frontend);
return (
<div className="home">
<div className="skills">
<h1>Skills</h1>
{frontend.map((item, index) => {
console.log(index)
return <ul key={index}>
<li>{item.id}</li>
</ul>;
})}
</div>
</div>
);
};
It seems your frontend.map((item, index) pointed to nested array, the simplest way was like this if you cannot change your backend result:
frontend[0].map((item, index)

Checkboxes are not working properly in React js

I am assigned a simple task to render permissions of different users using React JS.
There is a little problem and I think the page is not rendered according to the received props data.
Here is my code with little bit explanation.
// my App.js file
import { useState } from "react";
import "./App.css";
import Dropdown from "./components/Dropdown";
import Permissions from "./components/Permissions";
function App() {
const users = [
{
id: 1,
name: "Cirilla",
permissions: ["Post"],
},
{
id: 2,
name: "Michael Scofield",
permissions: ["Post", "Fetch", "Write"],
},
{
id: 3,
name: "Thomas Shellby",
permissions: [],
},
{
id: 4,
name: "Jon Snow",
permissions: ["Fetch", "Post"],
},
];
let [currentUser, setCurrentUser] = useState(users[0]);
const permissions = [
{
id: 1,
name: "Post",
val: currentUser.permissions.includes("Post"),
},
{
id: 2,
name: "Fetch",
val: currentUser.permissions.includes("Fetch"),
},
{
id: 3,
name: "Write",
val: currentUser.permissions.includes("Write"),
},
{
id: 4,
name: "Read",
val: currentUser.permissions.includes("Read"),
},
];
const dropDownChangeHandler = (value) => {
/*this function is executed whenever the dropdown is value is changed. setCurrentUser causes the app function to run again and the array permissions is created again according to the selected user*/
const user = users.find((item) => item.name === value);
setCurrentUser(user);
};
console.log(currentUser);
return (
<div className="container">
<Dropdown list={users} onChange={dropDownChangeHandler} />
<Permissions list={permissions} />
</div>
);
}
export default App;
Here is the permissions.js file
import PermissionsItem from "./PermissionsItem";
const Permissions = (props) => {
return (
<div>
{props.list.map((item) => (
<PermissionsItem key={item.id} item={item} />
))}
</div>
);
};
export default Permissions;
And finally, here is the permissionItem.js file
import React, { useEffect, useState } from "react";
const PermissionsItem = (props) => {
/* const [checkboxValue, setCheckBoxValue] = useState(props.item.val); // here useState does not provide the correct value so I have to use useEffect for this */
useEffect(() => {
setCheckBoxValue(props.item.val);
}, [props.item.val]);
const checkBoxChangeHandler = (event) => {
setCheckBoxValue(event.target.checked);
};
return (
<div className="permission-item">
<label htmlFor={props.item.id} className="perm-li">
{props.item.name}
</label>
<input
id={props.item.id}
type="checkbox"
checked={checkboxValue}
onChange={checkBoxChangeHandler}
/>
</div>
);
};
export default PermissionsItem;
The problem is that when I check any checkbox value of any user (suppose Cirilla), and then select the other user from dropdown (suppose Michael Scofield), the checked permission of first user, Cirilla, is also checked in Michael Scofield's permission. The Micheal's data is displayed correctly in the console but checkboxes are not rendered accordingly.
Please Help I have already wasted my whole week on this :( Any kind of help or suggestion is much appreciated. Thank you in advance !
The problem is that your do check by user in permission. There is no dependecy between the "permission" component and currentUser, so it does not render.
App:
const users = [
{
id: 1,
name: "Cirilla",
permissions: ["Post"],
},
{
id: 2,
name: "Michael Scofield",
permissions: ["Post", "Fetch", "Write"],
}
///...
];
const permissions = [
{
id: 1,
name: "Post"
},
{
id: 2,
name: "Fetch"
}
///...
];
const dropdownChange = (e) => {
setCurrentUser(users.find(x => x.id == e.target.value))
}
return (
<div className="App">
<div className="container">
<select value={currentUser?.id} onChange={dropdownChange} >
{users.map((item) => {
return <option value={item.id}>{item.name}</option>})
}
</select>
<Permissions list={permissions} currentUser={currentUser}/>
</div>
</div>
);
Permission and PermissionItem
const Permissions = (props) => {
return (
<div>
{props.list.map((item) => (
<PermissionsItem
key={item.id}
item={item}
hasItem={props.currentUser.permissions?.includes(item.name)}/>
))}
</div>
);
};
const PermissionsItem = (props) => {
const [checkboxValue, setCheckBoxValue] = useState(false);
useEffect(() => {
setCheckBoxValue(props.hasItem)
},[props.hasItem])
const checkBoxChangeHandler = (event) => {
//TODO users update
setCheckBoxValue(event.target.checked);
};
return (
<div className="permission-item">
<label htmlFor={props.item.id} className="perm-li">
{props.item.name}
</label>
<input
id={props.item.id}
type="checkbox"
checked={checkboxValue}
onChange={checkBoxChangeHandler}
/>
</div>
);

User preferred language saved but the page content language didn't change only after I reload

I'm using ant design pro.
The idea is In the platform we have 2 languages to choose from Fr(French) and En(English),
I want the user when he logs in and change the language to English for example when he logs out and log in again the language should be saved to English so he would be able to see the content in English, I managed to do it, when i login in the backend the preferedLanguage = en, the language toggle in the also changes to en, the only problem the web page content stays in French it's only change in English when i reload the page.
I think the issue is related to the login page, the login page is set to French as default , let's say my preferred language now is English, if i login from the login page. The page content loaded in French only changes when i reload.
-This is the umijs documentation : https://umijs.org/docs/max/i18n#setlocale-%E8%AE%BE%E7%BD%AE%E8%AF%AD%E8%A8%80
-LanguageDropdown (the toggle where you select the language (Fr or En)
import type { FC } from 'react';
import React, { useState, useEffect } from 'react';
import { Menu, Dropdown } from 'antd';
import { CaretDownOutlined, CaretUpOutlined, GlobalOutlined } from '#ant-design/icons';
import styles from './index.less';
import { setLocale, getLocale, getAllLocales } from 'umi';
interface Props {
setUpdateLang: any;
currentLang: string;
}
const LanguageDropdown: FC<Props> = ({ currentLang, setUpdateLang }) => {
const [langvisible, setLangVisible] = useState<boolean>(false);
const [localesList, setLocalesList] = useState<any[]>([]);
const [currentLocale, setCurrentLocale] = useState<string>('');
// useEffect(() => {
// if (currentLang) {
// setLocalesList(getAllLocales());
// setCurrentLocale(getLocale());
// setLocale(currentLang === 'fr' ? 'fr-FR' : 'en-US');
// }
// alert(currentLang);
// alert(getLocale());
// }, [currentLang]);
useEffect(() => {
setLocalesList(getAllLocales());
setCurrentLocale(getLocale());
if (currentLang) {
// alert(222);
const selectedLang = currentLang === 'fr' ? 'fr-FR' : 'en-US';
// setNewLang(selectedLang);
setLocale(selectedLang, false);
setCurrentLocale(getLocale());
}
}, [currentLang]);
const onLangVisibleChange = (visibleLang: boolean) => {
setLangVisible(visibleLang);
};
const langNameHandler = (lang: string) => {
if (lang === 'en-US') return 'EN';
else if (lang === 'fr-FR') return 'FR';
return 'FR';
};
const setNewLang = (lang: string) => {
setUpdateLang({ lang: langNameHandler(lang).toLocaleLowerCase(), updated: true });
setLocale(lang);
};
const Langmenu = (
<Menu>
{localesList?.map((lang: any) => (
<Menu.Item key={lang}>
<a onClick={() => setNewLang(lang)}>{langNameHandler(lang)}</a>
</Menu.Item>
))}
</Menu>
);
return (
<div className={styles.profileDropdownContainer}>
<Dropdown
overlay={Langmenu}
placement="bottomLeft"
trigger={['click']}
onVisibleChange={onLangVisibleChange}
className={styles.dropdown}
>
<div className={styles.langContainer}>
<span>
<GlobalOutlined /> {langNameHandler(currentLocale)}
</span>
{!langvisible ? <CaretDownOutlined /> : <CaretUpOutlined />}
</div>
</Dropdown>
</div>
);
};
export default LanguageDropdown;
-RightContext
import { Tag } from 'antd';
import type { Settings as ProSettings } from '#ant-design/pro-layout';
import React, { useEffect, useState } from 'react';
import type { ConnectProps } from 'umi';
import type { Dispatch } from 'umi';
import { connect } from 'umi';
import type { ConnectState } from '#/models/connect';
import Avatar from './AvatarDropdown';
import styles from './index.less';
import LanguageDropdown from '../languageDropdown';
import moment from 'moment';
export type GlobalHeaderRightProps = {
dispatch: Dispatch;
theme?: ProSettings['navTheme'] | 'realDark';
auth: any;
users: any;
platformLanguage: any;
data: any;
} & Partial<ConnectProps> &
Partial<ProSettings>;
const ENVTagColor = {
dev: 'orange',
test: 'green',
pre: '#87d068',
};
const GlobalHeaderRight: React.FC<GlobalHeaderRightProps> = (props) => {
const [updateLang, setUpdateLang] = useState<{ lang: string; updated: boolean }>({
lang: '',
updated: false,
});
const [currentLang, setCurrentLang] = useState<any>(null);
const { theme, layout, auth, platformLanguage, data, dispatch } = props;
let className = styles.right;
useEffect(() => setCurrentLang(platformLanguage), [platformLanguage]);
useEffect(() => {
if (updateLang.updated) {
const {
organization,
roles,
email,
deleted,
department,
createdById,
organizationId,
...rest
} = data;
const birthdate = moment(rest.birthdate).format('YYYY-MM-DD');
const workversary = moment(rest.workversary).format('YYYY-MM-DD');
dispatch({
type: 'users/updateMe',
payload: {
data: { ...rest, birthdate, workversary, platformLanguage: updateLang.lang },
userId: auth?.currentUser.id,
},
});
setUpdateLang({ ...updateLang, updated: false });
setCurrentLang(updateLang.lang);
}
}, [updateLang]);
if (theme === 'dark' && layout === 'top') {
className = `${styles.right} ${styles.dark}`;
}
return (
<div className={className}>
{currentLang ? (
<LanguageDropdown currentLang={currentLang} setUpdateLang={setUpdateLang} />
) : null}
<Avatar />
{REACT_APP_ENV && (
<span>
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
</span>
)}
</div>
);
};
export default connect(({ settings, auth, users }: ConnectState) => ({
theme: settings.navTheme,
layout: settings.layout,
auth,
users,
platformLanguage: auth?.currentUser?.membership?.platformLanguage,
data: auth?.currentUser?.membership,
}))(GlobalHeaderRight);
-LoginLayout
import React, { useEffect, useState } from 'react';
import type { ConnectState } from '#/models/connect';
import type { MenuDataItem } from '#ant-design/pro-layout';
import { getMenuData, getPageTitle } from '#ant-design/pro-layout';
import { useIntl, connect } from 'umi';
import type { ConnectProps } from 'umi';
import { Col, Row } from 'antd';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import LoginImage from '../assets/loginImage.png';
import SignUpAdminImage from '../assets/adminSignup.svg';
import styles from './LoginLayout.less';
import LanguageDropdown from '#/components/languageDropdown';
import SignupSideText from '#/components/SignupSideText';
export type UserLayoutProps = {
breadcrumbNameMap: Record<string, MenuDataItem>;
} & Partial<ConnectProps>;
const LoginLayout: React.FC<UserLayoutProps> = (props) => {
const [layoutImage, setLayoutImage] = useState(LoginImage);
const [updateLang, setUpdateLang] = useState<{ lang: string; updated: boolean }>({
lang: '',
updated: false,
});
const [currentLang, setCurrentLang] = useState<any>('');
useEffect(() => {
if (updateLang.updated) {
setUpdateLang({ ...updateLang, updated: false });
setCurrentLang(updateLang.lang);
}
}, [updateLang]);
useEffect(() => {
if (window.location.pathname === '/user/adminSignup/step1') {
setLayoutImage(SignUpAdminImage);
} else if (window.location.pathname === '/user/adminSignup/step2') {
setLayoutImage('TextSignup');
} else setLayoutImage(LoginImage);
}, [window.location.pathname]);
const {
route = {
routes: [],
},
} = props;
const { routes = [] } = route;
const {
children,
location = {
pathname: '',
},
} = props;
const { formatMessage } = useIntl();
const { breadcrumb } = getMenuData(routes);
const title = getPageTitle({
pathname: location.pathname,
formatMessage,
breadcrumb,
...props,
});
return (
<>
<HelmetProvider>
<Helmet>
<title>{title}</title>
<meta name="description" content={title} />
</Helmet>
<div className={styles.container}>
<Col
xl={{ span: 12, order: 1 }}
xs={{ span: 0, order: 2 }}
md={{ span: 0, order: 2 }}
lg={{ span: 0, order: 2 }}
style={{ backgroundColor: '#00bfa5' }}
>
{layoutImage === 'TextSignup' ? (
<SignupSideText />
) : (
<img alt="logo" width="100%" height="100%" src={layoutImage} />
)}
</Col>
<Col
xl={{ span: 12, order: 2 }}
lg={{ span: 24, order: 2 }}
sm={{ span: 24, order: 1 }}
xs={{ span: 24, order: 1 }}
>
{' '}
<Row justify="end" className="languageRow">
<LanguageDropdown currentLang={currentLang} setUpdateLang={setUpdateLang} />
</Row>
{children}
</Col>
</div>
</HelmetProvider>
</>
);
};
export default connect(({ settings }: ConnectState) => ({ ...settings }))(LoginLayout);

React-Redux. After changing state by useDispatch, components not updating by useSelector

I have useSelectors to check if my App component is updating. The first at the beginning of App component and the second one at App return part. By clicking on letters, currendElementId in store is updating with no problem (I checked by Redux DevTools). But useSelectors not updating.
I know that state should update in reducers immutable, but in createSlice we may use mutable code, so that's not my case. (Anyway, I have already tried to make state copy, change it and then send it, but it works same way)
There are my code:
store.js
import { configureStore } from "#reduxjs/toolkit";
import pagesReducer from "./../features/Pages/pagesSlice.js";
export default configureStore({
reducer: {
pagesInfo: pagesReducer,
},
})
pageSlice.js
import { createSlice, nanoid } from "#reduxjs/toolkit";
const initialState = {
currentPage: 0,
currentElementId: null,
pages: [ // Pages
{ // Page
id: nanoid(),
lines: [
{ // Line
id: nanoid(),
aligned: "left",
content: [
{ // Symbol
id: nanoid(),
type: "symbol",
symbol: "F",
isBold: false,
isItalic: false,
isUnderlined: false,
fontSize: 18,
color: "black",
},
{ // Symbol
id: nanoid(),
type: "symbol",
symbol: "o",
isBold: false,
isItalic: false,
isUnderlined: false,
fontSize: 18,
color: "black",
},
{ // Symbol
id: nanoid(),
type: "symbol",
symbol: "r",
isBold: false,
isItalic: false,
isUnderlined: false,
fontSize: 18,
color: "black",
},
],
},
{
id: nanoid(),
aligned: "left",
content: [
{ // Image
id: nanoid(),
type: "image",
imageSrc: "./img/me and the boys.png",
width: 200,
height: 200,
},
],
},
],
},
],
}
const textSlice = createSlice({
name: "pagesInfo",
initialState,
reducers: {
changeCurrentElementID(state, action) {
state.currentElementId = action.payload;
// return {
// ...state,
// currentElementId: action.payload,
// }
}
},
})
export const { changeCurrentElementID } = textSlice.actions;
export default textSlice.reducer;
index.js
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import store from "./app/store.js";
import { Provider } from 'react-redux';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
App.js
import css from "./App.module.css";
// import BoldingTextButton from "./features/BoldingTextButton/BoldingTextButton.js";
import "./nullStyle.css";
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { changeCurrentElementID } from "./features/Pages/pagesSlice.js";
import EnterImageButton from "./features/Pages/EnterImage/EnterImageButton.js";
import TextSizing from "./features/Pages/TextSizing/TextSizing.js";
import TextDecoration from "./features/Pages/TextDecoration/TextDecoration.js";
import TextAligning from "./features/Pages/TextAligning/TextAligning.js";
function App(props) {
console.log(useSelector(state => state.currentElementId));
const dispatch = useDispatch();
// document.addEventListener("click", event => {
// const target = event.target.closest("li")
// if (target) {
// const elementID = target.getAttribute("elementid");
// dispatch(changeCurrentElementID(elementID));
// }
// })
const changeElementID = event => {
const target = event.target.closest("li")
if (target) {
const elementID = target.getAttribute("elementid");
dispatch(changeCurrentElementID(elementID));
}
}
const GetPageContent = () => {
const rawPageLinesContent = useSelector(state => state.pagesInfo.pages[state.pagesInfo.currentPage].lines);
const currentElementID = useSelector(state => state.currentElementId);
const completedPageContent = rawPageLinesContent.map(line => {
return (
<ul key={line.id} className={css["page-line"]}>
{
line.content.map(element => {
let finalElement;
if (element.type == "symbol") {
const style = { fontSize: element.fontSize + "px" }
finalElement = (
<li onClick={changeElementID} key={element.id} elementid={element.id} className={`${css["page-line__item"]} ${css["page-line__symbol"]}`} style={style}>{element.symbol}</li>
)
if (currentElementID == element.id) {
finalElement = (
<input key={element.id} elementid={element.id} maxLength="1" className={`${css["page-line__item"]} ${css["page-line__symbol"]} ${css["page-line__choosen"]}`} style={style} value={element.symbol} />
)
}
}
else if (element.type == "image") {
finalElement = (
<li onClick={changeElementID} key={element.id} elementid={element.id} className={`${css["page-line__item"]} ${css["page-line__image"]}`}>
<img src={element.imageSrc} width={element.width} height={element.height} alt="image" />
</li>
)
}
// else if (element.type == "enter") {
// finalElement = (
// <li key={element.id} elementid={element.id} className={`${css["page-line__item"]} ${css["page-line__image"]}`}>
// <br />
// </li>
// )
// }
return finalElement;
})
}
</ul >
)
})
return completedPageContent;
}
return (
<div className={css["App"]}>
<header className={`${css['App__header']} ${css['tools']} `}>
<EnterImageButton />
<TextSizing />
<TextDecoration />
<TextAligning />
<div>{useSelector(state => state.currentElementId) || 0}</div>
</header >
<div className={`${css['App__content']} ${css['pages']} `}>
<div className={`${css['pages__item']}`} >
{GetPageContent()}
</div>
</div>
</div >
);
}
export default App;
Your selector is wrong.
Since you have
export default configureStore({
reducer: {
pagesInfo: pagesReducer,
},
})
your pages slice is mounted as slice.pagesInfo.
So you need to do
useSelector(state => state.pagesInfo.currentElementId)

React Error - 'deleteNinja' is not defined no-undef

I want to delete state data by Id I passed the function as a props. but I am getting error in Ninja.js file saying-
Failed to compile
src\Ninjas.js
Line 11:41: 'deleteNinja' is not defined no-undef
I don't understand why I am getting error.
App.js file-
import Ninjas from './Ninjas';
import React, { useState } from "react";
import AddNinja from './AddNinja';
function App() {
const [ ninjas , setNinja ] = useState([
{ name: 'Pratik', age: 23, belt:'Black', id: 1 },
{ name: 'Yash', age: 20, belt:'Green', id: 2 },
{ name: 'Smit', age: 20, belt:'Pink', id: 3 }
]) ;
const addNinja = (ninja) => {
ninja.id = Math.random();
setNinja([...ninjas , ninja]);
};
const deleteNinja = (id) => {
setNinja(ninjas.filter(ninja => {
return ninja.id !== id
}));
};
return (
<div className="App">
<header className="App-header">
<h1>My First react App</h1>
<Ninjas ninjas = { ninjas } deleteNinja = { deleteNinja } />
<AddNinja addNinja = { addNinja } />
</header>
</div>
);
}
export default App;
Ninja.js file :-
import React from 'react';
const Ninjas = ({ ninjas }) => {
const ninjaList = ninjas.map(ninja => {
return ninja.age > 19 ? (
<div className="ninja" key = { ninja.id }>
<div>Name: { ninja.name }</div>
<div>Age: { ninja.age }</div>
<div>Belt: { ninja.belt }</div>
<button onClick={() => {deleteNinja(ninja.id) }}>Delete Ninja</button>
</div>
)
: null;
})
return(
<div className='ninja-list'>
{ ninjaList }
</div>
)
}
export default Ninjas;
There is no deleteNinja prop in Ninjas component.
Change code like below:
...
const Ninjas = ({ ninjas, deleteNinja }) => {
...

Categories

Resources