before I'll explain my problem I want to mention that the following snippet may not make sense however it should suffice to explain my problem.
I'm building a simple todo list and using useContext in conjunction with useReducer hooks.
within the following component, I'm generating the todo items with a button that will remove the designated item.
I've tried to add an onClick event that will dispatch a reducer event directly inside the Image component.
this implementation introduced an infinite loop however if I'm following the implementation described in the code below, my code works perfectly fine.
can someone shed light on what's going on? shouldn't the function create an infinite loop as well?
import type { NextPage } from 'next';
import Image from 'next/image';
import { useContext } from 'react';
import ListContext from '../context/list-context';
import Check from '../public/icon-check.svg';
import Cross from '../public/icon-cross.svg';
const ListItems : NextPage = () => {
const {state, dispatch} = useContext(ListContext);
const testingFunc = () => {
console.log("sssssss");
dispatch({type: 'removingElement', payload : 'Google'});
}
return (
<ul>
{state.map(item => <li className='border-b'>
<button onClick={testingFunc} className='bg-black border-2 border-red-900 p-6 rounded-full'>
<Image src={Check} />
</button>
{item.name} <button className='border-2 border-red-900 p-2 rounded-full'>
<Image src={Cross} />
</button>
</li>)}
</ul>
)
}
export default ListItems;
Related
I am running into a slight problem when trying to render a React Bootstrap Icon in Next.js.
I am using getStaticProps to make a call to the Notion API, to then use as props in my page, and everything is working fine.
However, I would like to define which icon to use in the Notion CMS.
According to the React Bootstrap Icons package on NPM you can do it this way, however I am not using TypeScript so I edited the code slightly (further below):
Icons.js
import * as icons from 'react-bootstrap-icons';
export const Icon = ({ iconName, ...props }) => {
const BootstrapIcon = icons[iconName];
return <BootstrapIcon {...props} />;
}
Services.js
import React from 'react';
import Card from 'react-bootstrap/Card';
import CardGroup from 'react-bootstrap/CardGroup';
import { Icon } from '../icons';
function Services({data}) {
const renderItems = data?.map((record) => {
// saving notion data as variables
let icon = record.properties.Icon.title[0].text.content
let title = record.properties.Service.rich_text[0].plain_text
let description = record.properties.Descrip.rich_text[0].text.content
return <Card key={record.id}>
<Icon
iconName={icon}
color="#96DBAE"
size={96}
/>
<Card.Body>
<Card.Title>{title}</Card.Title>
<Card.Text>{description}</Card.Text>
</Card.Body>
</Card>
})
return (
<>
<section >
<CardGroup>
{renderItems}
</CardGroup>
</section>
</>
);
}
export default Services;
I am running into this error. When I console.log(icon) it displays as a string, however when I pass the variable as a prop on the Icon, the error shows. If I type a regular string e.g iconName={"Globe"} everything works fine.
Any ideas how to solve this or where I might be going wrong? Any help is massively appreciated!
I am trying to write the tests for the NavBar component (using react-native-testing-library) that has several buttons that are basically just icons (using ui-kitten for react native). So I can't get these buttons by text (as there is none) but other methods didn't work for me either (like adding accesibilityLabel or testID and then getting by the label text / getting by test ID). Any ideas what I am doing wrong?
// NavBar.tsx
import React from 'react';
import {View, StyleSheet} from 'react-native';
import {HomeBtn, SaveBtn} from '../components/buttons';
import UserSignOut from './UserSignOut';
const NavBar = ({
navigation,
pressHandlers,
}) => {
return (
<View style={styles.navBar}>
<View>
<HomeBtn navigation={navigation} />
<SaveBtn pressHandler={pressHandlers?.saveBtn ?? undefined} />
</View>
<UserSignOut />
</View>
);
};
export default NavBar;
// HomeBtn.tsx
import React from 'react';
import {Button} from '#ui-kitten/components';
import {HomeIcon} from '../shared/icons';
import styles from './Btn.style';
export const HomeBtn = ({navigation}: any) => {
return (
<Button
accesibilityLabel="home button"
style={styles.button}
accessoryLeft={props => HomeIcon(props, styles.icon)}
onPress={() => navigation.navigate('Home')}
/>
);
};
// NavBar.test.tsx
import React from 'react';
import {render, screen} from '#testing-library/react-native';
import * as eva from '#eva-design/eva';
import {RootSiblingParent} from 'react-native-root-siblings';
import {EvaIconsPack} from '#ui-kitten/eva-icons';
import {ApplicationProvider, IconRegistry} from '#ui-kitten/components';
import NavBar from '../../containers/NavBar';
describe('NavBar', () => {
const navBarContainer = (
<RootSiblingParent>
<IconRegistry icons={EvaIconsPack} />
<ApplicationProvider {...eva} theme={eva.light}>
<NavBar />
</ApplicationProvider>
</RootSiblingParent>
);
it('should render the buttons', async () => {
render(navBarContainer);
// this test fails (nothing is found with this accesibility label)
await screen.findByLabelText('home button');
});
});
Query predicate
The recommended solution would be to use:
getByRole('button', { name: "home button" })
As it will require both the button role, as well as check accessibilityLabel with name option.
Alternative, but slightly less expressive way would be to use:
getByLabelText('home button')
This query will only check accessibilityLabel prop, which also should work fine.
Why is query not matching
Since you're asking why the query is not working, that depends on your test setup. It seems that you should be able to use sync getBy* query and do not need to await findBy* query, as the HomeBtn should be rendered without waiting for any async action.
What might prevent that test from working could be incorrect mocking of any of the wrapping components: RootSiblingParent, ApplicationProvider, they might be "consuming" children prop without rendering it. In order to diagnose the issue you can use debug() function from RNTL to inspect the current state of rendered components. You can also run your tests on render(<NavBar />) to verify that.
Does await screen.findByA11yLabel('home button') work? It should match the accessibilityLabel prop.
Im new in react.
I'm Created two file App.js and UseEffect.js
I'm Learn about lifecycle in react with function.
So When I See in console, that's render multiple time.
You can see my picture below.
My Console In Browser
This Is My Code
UseEffect.js
import React, {useState, useEffect} from "react";
function MyFunction(){
console.log('-> Function Init')
const [count, setCount] = useState(0)
const handleCount = () => {
setCount(prevState => {
return prevState+1
})
}
//LifeCycle
useEffect(() => {
console.log('my first effect')
})
console.log(`-> Start Render (${count})`)
return(
<div>
<h1>Function Component</h1>
<p>
<button onClick={handleCount}>Count</button>
{count}
</p>
</div>
)}
export default MyFunction
App.Js
import './App.css';
import UseEffect from './components/UseEffect'
function App() {
return (
<div className="App">
<UseEffect />
</div>
);
}
export default App;
How do it's work?, I Want it. it's just render one times.
Your useEffect call is missing a dependency array. When you want it to run only at the initial render, you need to pass it an empty array as its dependencies.
useEffect(() => {
console.log('my first effect')
}, [])
For further details, see this question.
Why it renders twice:
It's an intentional feature of the StrictMode. This only happens in development, and helps find accidental side effects put into the render phase. We only do this for components with Hooks because those are more likely to accidentally have side effects in the wrong place.
-gaearon
TLDR: It's a feature not a bug.
I am new to react and trying to refactor some es6 js code in to react I have a component that I need to create once I click on an icon similar to insert adjacent html is vanilla js any idea how can I achieve this.
import React, {useState} from 'react'
import Item from './Item';
import { icon, library } from '#fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faPlusCircle} from '#fortawesome/free-solid-svg-icons';
library.add(faPlusCircle)
function row(props) {
const [item] = useState(<Item />)
return (
<ul className="global">
item
<FontAwesomeIcon onClick={()=>{return <ChangeableItem/>}} con={["fas", "plus-circle"]}/>
<ul/>
)
}
This doesn't do anything:
onClick={()=>{return <ChangeableItem/>}}
The click handler isn't expecting a returned React node and won't do anything with it.
should I use state
Yes. Track in state whether or not this component is displayed. For example:
const [showChangeableItem, setShowChangeableItem] = useState(false);
The state now says not to show the "changeable item". Within the rendering, conditionally render that element based on state. For example:
{ showChangeableItem ? <ChangeableItem/> : null }
Then in your click handler you'd just update the state:
<FontAwesomeIcon onClick={() => setShowChangeableItem(true)} con={["fas", "plus-circle"]}/>
Basically, don't think of it as trying to add elements. All of the elements you need should already be specified in the render, some can just be wrapped in conditional logic. State drives the rendering. Events update state.
You would use a state variable for that.
import React, {useState} from 'react'
import Item from './Item';
import { icon, library } from '#fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faPlusCircle} from '#fortawesome/free-solid-svg-icons';
library.add(faPlusCircle)
function row(props) {
const [showItem, set_showItem] = useState
return (
<> // use react fragment here, otherwise you will get an error if you try to return several React Elements
<ul className="global">
{showItem? <Item> : null} // return the Item if you want to show it, otherwise return null
<FontAwesomeIcon
onClick={()=> set_showItem(true)}
con={["fas", "plus-circle"]}
/>
<ul/>
</> //ent of React fragment
)
}
I created a survey page, but when someone doesn't have credits I want to show a notification to the user using react-notifications, I've already tested the button and standalone it works, but when I added it to the tag using react-router-dom on an onClick event, the functions runs, but the notifications doesn't appear. Here's the code:
import React, { Component } from 'react';
import 'react-notifications/lib/notifications.css';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {NotificationContainer, NotificationManager} from 'react-notifications';
class Button extends Component {
createNotification = () => {
return () => {
switch (this.props.auth.credits) {
case 0:
console.log(this.props.auth.credits);
NotificationManager.error('You have no credits', 'Click to close!', 5000, () => {
});
break;
}
};
};
render() {
return (
<div>
<div className="fixed-action-btn">
<Link to="/surveys/new" className="btn-floating btn-large red" onClick={this.createNotification()}>
<i className="material-icons">add</i>
</Link>
</div>
<NotificationContainer/>
</div>
);
}
}
function mapStateToProps({ auth }){
return { auth };
}
export default connect(mapStateToProps)(Button);
So, when I test this on:
import React from 'react';
import Surveys from './surveys/Surveys';
import Button from '../utilities/addButton';
const Board = () => {
return (
<div>
<Surveys />
<Button />
</div>
);
};
export default Board;
It shows the button, and when clicked without credits, it console.logs the 0 credits, but, it just redirects to the referenced page without showing the notification created.
On my side, it doesn't appear an error neither in the terminal nor in the console or network. But still, the notification is processed but not shown.
So my question is: Is it possible to make the notification appear when the tag redirects to the new page, the only way that I see a solutions if it's not possible is making a conditional to stop the tag to make the change, am I wrong?
Thanks in advance.
Sorry if my question is not properly presented or written, is my first question here.
onClick prop for Link accept function reference. so try replacing
<Link to="/surveys/new" className="btn-floating btn-large red" onClick={this.createNotification}>
<i className="material-icons">add</i>
</Link>
This may be a Very Late reply but for those who didnt answer its because Link doesnt accept onCLick... try for html or with react or reactbootstrap package