score:1
render all items, even if they are filtered out, and just hide the items filtered out using css (display: none
):
const printlist = () => {
//if tag in filter has been added
if (state.tags.length > 0) {
// create a set of tags in state once
const tagsset = new set(state.tags.map(item => item.id));
return data.assets.map(elem => {
//hide if no tag is found
const hideelem = !elem.tags.some(item => tagsset.has(item.id));
//if found, return asset
return <item key={elem.title} data={elem} hide={hideelem} />;
})
} else {
return data.assets.map(elem => (<item key={elem.title} data={elem} /> ));
}
};
and in the item itself, use the hide
prop to hide the item with css using the style
attribute or a css class:
return (
<div classname="item" style={{ display: props.hide ? 'none' : 'block' }}>
you can also simplify printlist()
a bit more, by always creating the set, even if state.tags
is empty, and if it's empty hideelem
would be false
:
const printlist = () => {
const tagsset = new set(state.tags.map(item => item.id));
return data.assets.map(elem => {
//hide if state.tags is empty or no selected tags
const hideelem = tagsset.size > 0 && !elem.tags.some(item => tagsset.has(item.id));
//if found, return asset
return (
<item key={elem.title} data={elem} hide={hideelem} />
);
})
};
score:1
the problem that you are facing is that the cards that disappear are unmounted, meaning that their state is lost. the best solution is keeping the new custom tags you add to cards in the parent component, so it's persistent, no matter if the card is mounted or not. here are the modified files:
parent component
import react, {usestate} from 'react';
import item from './item'
import data from '../../data.json';
import './assets.scss'
function assets() {
const [state, updatemethod] = usestate({tag: "", tags: []});
const [childrentags, setchildrentags] = usestate(data.assets.map(elem => elem.tags));
const addchildrentag = (index) => (tag) => {
let newtags = array.from(childrentags)
newtags[index] = [...newtags[index], tag]
setchildrentags(newtags)
}
const removechildrentag = (index) => (i) => {
let newtags = array.from(childrentags)
newtags[index] = newtags[index].filter((elem, indx) => indx !== i)
setchildrentags(newtags)
}
const printlist = () => {
//if tag in filter has been added
if (state.tags.length > 0) {
return data.assets.map((elem, index) => {
//extract ids from obj into array
const dataarr = elem.tags.map(item => item.id);
const statearr = state.tags.map(item => item.id);
//check if tag is found in asset
const doestagexist = statearr.some(item => dataarr.includes(item));
//if found, return asset
if (doestagexist)
return (
<item
key={elem.title}
data={elem}
customtags={childrentags[index]}
addcustomtag={addchildrentag(index)}
removecustomtag={removechildrentag(index)}
/>
)
})
} else {
return data.assets.map((elem, index) => (
<item
key={elem.title}
data={elem}
customtags={childrentags[index]}
addcustomtag={addchildrentag(index)}
removecustomtag={removechildrentag(index)}
/>
));
}
};
const handleclick = () => {
const newtag = {id: state.tag, text: state.tag};
const copy = [...state.tags, newtag];
if (state.tag !== "") updatemethod({tag: "", tags: copy});
}
const handlechange = e => updatemethod({tag: e.target.value, tags: state.tags});
const handledelete = i => {
const copy = [...state.tags];
let removed = copy.filter((elem, indx) => indx !== i);
updatemethod({tag: state.tag, tags: removed});
}
return (
<div classname="assets">
<div classname="asset__filter">
<h3>add tags to filter</h3>
<ul classname="asset__tag-list">
{state.tags.map((elem, i) => (
<li classname="asset__tag" key={`${elem.id}_${i}`} >
{elem.text}
<button classname="asset__tag-del" onclick={() => handledelete(i)}>x</button>
</li>
))}
</ul>
<input
type="text"
value={state.tag}
onchange={handlechange}
placeholder="enter new tag"
classname="asset__tag-input"
/>
<button classname="asset__btn" onclick={handleclick}>add</button>
</div>
<div classname="item__list-holder">
{printlist()}
</div>
</div>
);
}
export default assets;
child component
import react, {usestate, useeffect} from 'react';
function item(props) {
const [state, updatemethod] = usestate({tag: ""});
cosnst tags = props.customtags
cosnst addcustomtag = props.addcustomtag
cosnst removecustomtag = props.removecustomtag
const handleclick = () => {
if (state.tag !== "") addcustomtag(state.tag);
}
const handlechange = e => updatemethod({tag: e.target.value});
const handledelete = i => {
removecustomtag(i);
}
const assets = props.data;
return (
<div classname="item">
<img src={assets.url} alt="assets.title"/>
<h1 classname="item__title">{assets.title}</h1>
<div classname="item__tag-holder">
<ul classname="item__tag-list">
{tags.map((elem, i) => (
<li classname="item__tag" key={`${elem.id}_${i}`} >
{elem.text}
<button classname="item__tag-del" onclick={() => handledelete(i)}>x</button>
</li>
))}
</ul>
<input
type="text"
value={state.tag}
onchange={handlechange}
placeholder="enter new tag"
classname="item__tag-input"
/>
<button classname="item__btn" onclick={handleclick}>add</button>
</div>
</div>
);
}
export default item;
hope this helps, i can add some comments if anything is unclear :)
Source: stackoverflow.com
Related Query
- How to maintain state of child components when they are filtered through the parent component?
- How to update (re-render) the child components in React when the parent's state change?
- How to optimize React components with React.memo and useCallback when callbacks are changing state in the parent
- How does React re-use child components / keep the state of child components when re-rendering the parent component?
- How can I access child components values from a parent component when they are added dynamically?
- React - How do i force child components to re render when parent state component changes?
- how can I make a scrollable component that scrolls to the latest children components automatically when I append a child component?
- How to avoid rerender all child components which in loop when parent component state update
- How to maintain state of child components of Sortable container?
- How to update parent state and child components props at once (at the same time)
- How to update the state of child components to drag them around independently
- React child components are only half updating when switching from one to the other
- How to fix "Uncaught Error: Objects are not valid as a React child" when passing objects, obtained from the blockchain, to the children components
- How to reinitialize the state with react hook when rerender the components
- How should I go about changing the state of siblings when a child is clicked in React?
- how to prevent child component from reload when the parent state is change
- How to let a parent component manage the state of child components in React?
- Making the state of a component affect the rendering of a sibling when components are rendered iteratively
- In which order are React components re-rendered when global state is updated through hooks?
- State is not updating from a function when the components are inside an array
- In ReactJs, How to Passing or retrieving state of a component into another such that both components are part of third component to divide the actions
- How can I set the state of my parent component from the child component when using react-router?
- React keys when handling dynamic children. What are they for? How are they used behind the scenes?
- React: Passed states to child components don't get updated when they change within the parent
- When I set state via useState in parent component, my props in the child I'm passing down to are undefined
- Is componentDidUpdate for the parent called when a child components state changes?
- How to let a parent component know when all the child component are loaded
- My State Does Change But Components Are Disappear When I Update My State In React Native How To Fıx This?
- how to maintain login and logout state globally and reflect the changes, when localstorage is used to save login and logout state globally in reactjs
- React.js child component not updating when props are changed through the parent
More Query from same tag
- How to get value of Date Picker from Material Ui
- My React UI wont update unless i refresh the page
- Creating collapsible table cells with Bootstrap 4 and ReactJS
- React syntax error, can't seem to figure out what the problem is. Error: JSX element 'div' has no corresponding closing tag.ts(17008)
- Webpack 5 - Asset Modules - png|jpg - Webpack Error
- TypeScript & React - one onChange Handler for multiple input fields
- Trying to call useContext outside of a function component
- Glitches while dragging the element fastly
- custom hooks for data fetch
- Updated - Changing the state from a functional child component
- React filtering array of object by input text and category selection by button click
- How to solve Invalid hook call in ReactJS?
- Very simple react destructuring issue with a custom hook
- I can’t seem to reliably remove a listener using componentWillUnmount
- How to call internal API from Rails view (for ReactJS prerender purpose)?
- React React-Bootstrap popover
- Testing a custom hook with useSelector
- Using capacitor-community/admob without ionic
- Typescript: How to dynamically add a method to a function with autocompletion?
- _worker.default is not a constructor in react js
- React: call custom hook from useEffect or run code before component mounts
- Error while conditional rendering of state value using ternary operator inside jsx in Reactjs 18.0
- State not setting correctly when Enter is pressed
- Why can't a getElementById method find an element when imported inside functional component?
- Design Redux actions and reducers for a React reusable component
- How can I assign a key to an item in my array in react js?
- react-bootstrap NavBar padding
- How can I change nested state in class component to state in functional component?
- React state change not causing re-render
- Redux Action not hitting Reducer [React]