I have an array of objects, I would like the click to retrieve a different a random object. I tried as below but it doesn't work. Thank you for help
I modified the post, I added the complete component so that you can see my problem
const data = [
{
firstname: "john",
lastname: "john"
},
{
firstname: "peter",
lastname: "peter"
}];
const RandomCollaborator = () => {
const test = data[Math.floor(Math.random() * data.length)]
console.log(test)
return test;
}
error console : NaN
const AccountComponent = () => {
const dispatch = useDispatch();
getListCollaboratorService(dispatch);
const [ errorListCollaborater, setErrorListCollaborater ] = useState(null);
const storageUserDetails = localStorage.getItem("userDetails");
const [listCollaborater, setListCollaborater] = useState("");
const userDetails= JSON.parse(storageUserDetails);
const storeListCollaborater = userDetails === null ? useSelector(state => state.reducerListCollaborater.state) : userDetails
useEffect(()=> {
setListCollaborater(localStorage.getItem("listCollaborater"))
}, [listCollaborater])
const test1 = listCollaborater
const RandomCollaborater = () => {
const test = Math.floor(Math.random() * test1.length)
return test;
}
return(
<div>
<div>
<RandomCollaborater />
</div>
)
}
export default AccountComponent;
Related
Here the REPL: https://svelte.dev/repl/56770fec88af4b76bdc8ea962178854e?version=3.42.1
Here the code:
App.svelte:
<script>
import {editableStore} from "./store";
let name = "John"
$: player = editableStore(name);
</script>
<h1>Hello {$player.name}!</h1>
<button on:click={() => name = (name === "Bob" ? "Jerry" : "Bob")}>
Change name
</button>
<h2>Log:</h2>
{#each $player.log as log}
<li>{log}</li>
{/each}
store.js:
import {writable} from "svelte/store";
const defaultStore = {
name: "Bob",
age: 18,
log: []
};
export const editableStore = (name) => {
console.log("Recreated with name:", name);
const {subscribe, update} = writable({...defaultStore}, () => () => clearInterval);
if (name) {
update(s => ({...s, name}));
}
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
return { subscribe };
};
As you can see if you click on "Change name" the store gets recreated.
This is what I need to avoid.
But how?
Instead of re-creating the store every time name changes, only create it once and set $player.name when name changes.
<script>
import {editableStore} from "./store";
let name = "John";
let player = editableStore(name);
$: $player.name = name;
</script>
This will require you to update your store method to return the set function.
export const editableStore = (name) => {
console.log("Recreated with name:", name);
// also destructure set here
const {subscribe, update, set} = writable({...defaultStore}, () => () => clearInterval);
if (name) {
update(s => ({...s, name}));
}
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
// also return set here
return { subscribe, set };
};
Try to instanciate your store as son as possible like in the ./store.js file and then use the set or update method instead of instanciate it in the component directly:
// store.js
import {writable} from "svelte/store";
const defaultStore = {
name: "Bob",
age: 18,
log: []
};
export const createEditableStore = () => {
const {subscribe, update, set} = writable({...defaultStore}, () => () => clearInterval);
const clearInterval = setInterval(() => {
update(s => ({...s, log: [...s.log, new Date()]}))
}, 1000)
return { subscribe, set, update };
};
export const player = createEditableStore()
<!-- App.svelte -->
<script>
import { player } from "./store";
let name = "John"
$: player.update(p => ({ ...p, name }))
</script>
<h1>Hello {$player.name}!</h1>
<button on:click={() => name = (name === "Bob" ? "Jerry" : "Bob")}>
Change name
</button>
<h2>Log:</h2>
{#each $player.log as log}
<li>{log}</li>
{/each}
Have a look at the REPL.
I have a mini-app that consists of a search bar and a table with data. The data is searchable using the search bar. I am using lodash debounce to filter the table data when a user enters something in the search bar. So far so good. The problem arises when the search word is erased by pressing the backspace. I want the table to restore the initial data when no input is entered or input is erased.
type IType = {company: string, city: string, domain: string}
export const App: React.FC = () => {
const [userInput, setUserInput] = useState<string>('');
const [tableData, setTableData] = useState<IType[]>(data);
const filterTable = ()=>{
const filteredData = tableData.filter((data)=>data.company.toLowerCase().includes(userInput)
|| data.city.toLowerCase().includes(userInput)
|| data.domain.toLowerCase().includes(userInput));
// eslint-disable-next-line no-console
console.log('filteredData', filteredData);
filteredData.length === data.length ? setTableData([...data]) : setTableData([...filteredData]);
};
const debouncedData = useCallback(debounce(filterTable, 1000), [userInput]);
useEffect(() => {
debouncedData();
}, [userInput]);
const onChangeHandler:
(event: React.ChangeEvent<HTMLInputElement>) => void = (event) => setUserInput(event.target.value);
return (
<div style={mainWrapper}>
<SearchBar userInput={userInput} onChangeHandler={onChangeHandler} />
<Table tableData={tableData}/>
</div>
);
}
;
You can do the conditional rendering.
If the search input is empty string, just display the original data and not the computed tableData.
type IType = {company: string, city: string, domain: string}
export const App: React.FC = () => {
const [userInput, setUserInput] = useState<string>('');
const [tableData, setTableData] = useState<IType[]>(data);
const filterTable = ()=>{
const filteredData = tableData.filter((data)=>data.company.toLowerCase().includes(userInput)
|| data.city.toLowerCase().includes(userInput)
|| data.domain.toLowerCase().includes(userInput));
// eslint-disable-next-line no-console
console.log('filteredData', filteredData);
filteredData.length === data.length ? setTableData([...data]) : setTableData([...filteredData]);
};
const debouncedData = useCallback(debounce(filterTable, 1000), [userInput]);
useEffect(() => {
debouncedData();
}, [userInput]);
const onChangeHandler:
(event: React.ChangeEvent<HTMLInputElement>) => void = (event) => setUserInput(event.target.value);
return (
<div style={mainWrapper}>
<SearchBar userInput={userInput} onChangeHandler={onChangeHandler} />
<Table tableData={userInput === "" ? data : tableData}/>
</div>
I have some JSON that is formatted like this:
{
card_id: "afe1500653ec682b3ce7e0b9f39bed89",
name: "A.J. Burnett",
playerattribute: {
team: "Marlins",
rarity: "Diamond",
}
}
I'm attempting to display the name and the team in a component. Here is what I have.
const PlayerProfile = ({ match, location }) => {
const { params: { cardId } } = match;
const [player, setPlayer] = useState(0);
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://127.0.0.1:8000/api/player-profiles/${cardId}/?format=json`,
).then((result) => {
setPlayer(result.data);
});
};
fetchData();
}, []);
return (
<Container component="main">
Name: {player.name}
Team: {player.playerattribute.team}
</Container>
)
}
export default PlayerProfile;
However, I get this error: TypeError: Cannot read property 'team' of undefined
The name works fine. So I'm assuming it's an issue with the nested JSON.
You probably shouldn't instanciate your player state with 0 if the projected value is an object.
The error comes up because you try to access a property of an object property that doesn't exist at creation.
Basically, your code tries to do this: {0.playerattribute.team}
0.playerattribute => undefined
Workaround would be a conditionnal render or a default initial value of your state that matches the JSX needs.
const PlayerProfile = ({ match, location }) => {
const { params: { cardId } } = match;
const [player, setPlayer] = useState({
name: "",
playerattribute: {
team: ""
}
});
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://127.0.0.1:8000/api/player-profiles/${cardId}/?format=json`,
).then((result) => {
setPlayer(result.data);
});
};
fetchData();
}, []);
return (
<Container component="main">
Name: {player.name}
Team: {player.playerattribute.team}
</Container>
)
}
export default PlayerProfile;
or
const PlayerProfile = ({ match, location }) => {
const { params: { cardId } } = match;
const [player, setPlayer] = useState(null);
useEffect(() => {
const fetchData = async () => {
const result = await axios(
`http://127.0.0.1:8000/api/player-profiles/${cardId}/?format=json`,
).then((result) => {
setPlayer(result.data);
});
};
fetchData();
}, []);
return (
<Container component="main">
Name: {player?.name}
Team: {player?.playerattribute?.team}
</Container>
)
}
export default PlayerProfile;
Set useState const [player, setPlayer] = useState("");
const [player, setPlayer] = useState({
Name: '',
Team: ''
}}
//on your setPlayer you may
const playerData = result.data;
setPlayer({
Name: playerData.name
Team: playerData.playerattribute.team})
if you still getting same error, please provide screenshot of console.log(result)
I am stuck on this for some reason. I know how to use .sort when there is a simple array. I am not quite sure how to sort a nested object in an array using a variable in that object. I can sort it, but I am not sure how to display it.
Here is what I am working with. I get data from a database and map over that data to display it. Everything works as expected. Now I want to take that data and sort it by artist.
Here is the code I am working with.
export default function ShowRecords() {
const classes = recordFormStyles();
const url = " http://localhost:5000";
//get userData state to use in useEffect
//set state for showing records in database and opening/closing modals
const [newRecords, newRecordData] = React.useState([]);
const [editOpen, handleEditModal] = React.useState(false);
const [addModalOpen, handleAddModal] = React.useState(false);
//set state for edit records
const [title, setTitle] = React.useState("");
const [artist, setArtist] = React.useState("");
const [rating, setRating] = React.useState("");
const [genre, setGenre] = React.useState("");
const [description, setDescription] = React.useState("");
const [userId, setUserId] = React.useState("");
//set state for favorite icon
const [favorite, setFavorite] = React.useState([]);
const fetchFavoriteData = async () => {
const result = await axios.get(url + "/favorite/get", authToken);
setFavorite(result.data);
};
const addFavorites = async (_id, title, artist, rating, genre, description, isFavorite) => {
const favorites = {
userId: _id,
title,
artist,
rating,
genre,
description,
isFavorite
};
const result = await axios.post(
url + "/favorite/add",
favorites,
authToken
);
setFavorite(result.data);
};
const deleteFavorite = async (title) => {
await axios.delete("http://localhost:5000/favorite/delete", {
data: { title: title },
authToken,
});
};
//functions to control state
const handleAddModalOpen = () => {
handleAddModal(true);
};
const handleCloseAddModal = () => {
handleAddModal(false);
};
const handleIsEditModalClose = () => {
handleEditModal();
};
//fetch record data
const fetchData = async () => {
const result = await axios.get(url + "/record/get", authToken);
newRecordData(result.data);
};
React.useEffect(() => {
fetchData();
fetchFavoriteData();
}, []);
// delete records
const deleteRecord = async (_id) => {
const deleteRecords = {
_id: _id,
};
await axios.delete(url + "/record/" + _id, deleteRecords).then((result) => {
const refresh = newRecords.filter((result) => result._id !== _id);
newRecordData(refresh);
});
};
//functions for controlling edit record state
const editRecord = (_id, title, artist, rating, genre, description) => {
setUserId(_id);
setTitle(title);
setArtist(artist);
setRating(rating);
setGenre(genre);
setDescription(description);
handleEditModal(true);
console.log(title);
};
//functions for setting favorite state and color and post request to add favorite
return (
<div>
{/* set props */}
<Favorites />
<AddRecord
isAddModalOpen={addModalOpen}
handleIsAddModalClose={handleCloseAddModal}
addNewRecords={newRecords}
handleIsAddModalOpen={handleAddModal}
refreshRecordData={newRecordData}
/>
<EditRecords
editModalOpen={editOpen}
handleCloseEditModal={handleIsEditModalClose}
editUserId={userId}
editTitle={title}
editArtist={artist}
editRating={rating}
editGenre={genre}
editDescription={description}
editTitleState={setTitle}
editArtistState={setArtist}
editRatingState={setRating}
editGenreState={setGenre}
editDescriptionState={setDescription}
editUrl={url}
editFetchData={fetchData}
editNewRecordData={newRecordData}
/>
<Button
className={classes.addButton}
onClick={() => handleAddModalOpen(true)}
>
Add Record
</Button>
<div className={classes.cardsContainer}>
<Grid container spacing={8} style={{ padding: 80 }} justify = "center">
{newRecords.length > 0 &&
newRecords.map((element) => (
<RecordCard
key = {element._id}
element={element}
editRecord={editRecord}
deleteRecord={deleteRecord}
addFavorites = {addFavorites}
deleteFavorite = {deleteFavorite}
favorite = {favorite}
/>
))}
</Grid>
</div>
</div>
);
}
I get the data in my uesEffect and I want to sort it using the Arist name. I am just unsure on how to do that. I couldn't find much googling.
Sort the data before you save it into state. The sort function can take in a function that returns -1, 0, 1 to determine how things should be ordered. The below example uses the localeCompare function to sort by the artist.
let data = [
{ artist: 'john', record: '1' },
{ artist: 'mary', record: '2' },
{ artist: 'bob', record: '3' }
];
let sorted = data.sort((a,b) => (a.artist.localeCompare(b.artist)));
console.log(sorted);
Below is my code with a search input hoos and I can't identify why it isn't working.
import Herois from './json/videos.json'
function App() {
const [valueInput, setValueInput] = useState('')
const [newArray, setNewArray] = useState([])
useEffect(() => {
const results = Herois.filter((i) => {
i.title.toLowerCase().includes(valueInput.toLowerCase())
})
setNewArray(results)
console.log(newArray)
}, [valueInput])
}
is always becoming an empty array
const results = Herois.filter((i) => {
// you have to return the something here
return i.title.toLowerCase().includes(valueInput.toLowerCase())
})
or
const results = Herois.filter((i) => (i.title.toLowerCase().includes(valueInput.toLowerCase())
))