I have a react return like so:
return (
<div className="App">
{data && (
<div>
{data.map((d) => {
return (
<div key={d.id}>
<div>{d.string}</div>
<div> {d.array.map((el) => {
<div>{el}</div>
})}
</div>
</div>
);
</div>
)}
</div>
);
Each {el} doesn't render but the array exists, if I try and render {d.array[0]} the first index of the array is rendered, so I'm not the issue. I don't get an error and nothing breaks. Is it a react issue or a javascript issue, or is my syntax wrong.
You need to add a key to each children of your second map so React knows each one is different:
return (
<div className="App">
{data && (
<div>
{data.map((d) => {
return (
<div key={d.id}>
<div>{d.string}</div>
<div> {d.array.map((el, index) => {
return <div key={index}>{el}</div>
})}
</div>
</div>
);
</div>
)}
</div>
);
before the "=>" of second map, will have use "()" and not "{}", because all that be in {is js}, and in (jsx).
After receiving data from the DB server, you try to render it, but the console log shows the data, but the component is not rendered. What's the reason?
useEffect(() => {
readRequest().then(setTodos);
console.log()
}, []);
return (
<div className="App">
{todos.map((todo) => {
console.log(todo);
console.log(todo.text);
<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>
})}
<p>dfdf</p>
</div>
);
The picture is a screen capture.
Your .map callback does not return anything.
Change the { to (:
return (
<div className="App">
{todos.map((todo) => ( // <-- here
<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>
))}
<p>dfdf</p>
</div>
);
Or use the return keyword.
return (
<div className="App">
{todos.map((todo) => {
return (<div key={todo._id}>
{todo.text}
{`${todo.completed}`}
</div>);
})}
<p>dfdf</p>
</div>
);
{middleMenu.map((column) => {
return (
<div className="row">
column.map((item) => {
const { title, image, path } = item;
return (
<ul className="footer-collections">
<MenuLinks title={title} image={image} path={path} />
</ul>
);
})
</div>
);
})}
Does anyone know what the solution is? My first time using 2D Arrays
use :
<div className="row">
{column.map((item) => {
const { title, image, path } = item;
return (
<ul className="footer-collections">
<MenuLinks title={title} image={image} path={path} />
</ul>
);
})}
</div>
As of right now I have a list of 40 or so Menu items that are grocery stores, and I only have the option to display all of the 40 stores at one time. I am trying to implement a filter by using a drop-down menu where you select the name of a store and only display stores with that name. Here is my code for the filter in a file called 'MenuComponent.js':
class FilterForm extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(values) {
console.log(values.filter);
}
render() {
return(
<LocalForm onSubmit={(values) => this.handleSubmit(values)}>
<Control.select model=".filter" id="filter" name="filter" className="form-control">
<option value="Safeway">Safeway</option>
<option value="Whole Foods">Whole Foods</option>
<option value="Luckys">Luckys</option>
<option value="Sprouts">Sprouts</option>
</Control.select>
<Row className="form-group">
<Col md={{size: 10, offset: 2}}>
<Button type="submit" color="primary">
Filter
</Button>
</Col>
</Row>
</LocalForm>
);
};
}
As part of this file I have the actual menu component as such, also located in 'MenuComponent.js':
const Menu = (props) => {
const menu = props.dishes.dishes.map((dish) => {
return (
<div key={dish.id} className="col-12 col-md-5 m-1">
<RenderMenuItem dish={dish} comments={props.comments.comments.filter((comments) => comments.dishId === dish.id)} />
</div>
);
});
if (props.dishes.isLoading) {
return(
<div className="container">
<div className="row">
<Loading />
</div>
</div>
);
}
else if (props.dishes.errMess) {
return(
<div className="container">
<div className="row">
<h4>{props.dishes.errMess}</h4>
</div>
</div>
);
}
else
return (
<div className="container">
<div className="row">
<div className="col-12">
<h3>STORES</h3>
<FilterForm />
<hr />
</div>
</div>
<div className="row">
{menu}
</div>
</div>
);
}
export default Menu;
I am getting the correct value for values.filter. My question is how do I pass up this values.filter and re-render my Menu item so that I am only displaying the items where dish.name === values.filter.
The parent component is in a file called 'MainComponent.js' and looks like this:
return (
<div id="MainDiv">
<Header />
<TransitionGroup>
<CSSTransition key={this.props.location.key} classNames="page" timeout={300}>
<Switch>
<Route path="/home" component={HomePage} />
<Route exact path="/aboutus" component={AboutPage} />
<Route exact path="/menu" component={() => <Menu dishes={this.props.dishes} comments={this.props.comments} />} />
<Route path="/menu/:dishId" component={DishWithId} />
<Route exact path="/contactus" component={() => <Contact resetFeedbackForm={this.props.resetFeedbackForm}
postFeedback={this.props.postFeedback} />} />
<Redirect to="/home" />
</Switch>
</CSSTransition>
</TransitionGroup>
<Footer />
</div>
);
This is where I am mapping the state and dispatch to props:
const mapStateToProps = state => {
return {
dishes: state.dishes,
comments: state.comments,
promotions: state.promotions,
leaders: state.leaders
}
}
const mapDispatchToProps = (dispatch) => ({
postComment: (dishId, rating, author, comment, masks, carts, sanitizer, monitor, oneway, register, card, numcust, gloves, curb, delivery) => dispatch(postComment(dishId, rating, author, comment, masks, carts, sanitizer, monitor, oneway, register, card, numcust, gloves, curb, delivery)),
fetchDishes: () => {dispatch(fetchDishes())},
resetFeedbackForm: () => { dispatch(actions.reset('feedback'))},
fetchComments: () => {dispatch(fetchComments())},
fetchPromos: () => {dispatch(fetchPromos())},
fetchLeaders: () => {dispatch(fetchLeaders())},
postFeedback: (firstname, lastname, telnum, email, agree, contactType, message) => dispatch(postFeedback(firstname, lastname, telnum, email, agree, contactType, message))
});
You can pass down a function from Menu that will be used in FilterForm to set a state variable in Menu. When FilterForm updates the state variable in Menu, the Menu will re-render with the new filter.
Since Menu is a functional component you can use the useState hook.
const Menu = (props) => {
const [filter, setFilter] = useState(null);
...
// then pass the function to FilterForm
<h3>STORES</h3>
<FilterForm setFilter={setFilter} />
<hr />
Add the setFilter to FilterForm onSubmit
handleSubmit(values) {
console.log(values.filter);
this.props.setFilter(values.filter); // calls Menu's setFilter
}
Now we have that value back in Menu
const Menu = (props) => {
const [filter, setFilter] = useState(null);
let dishes = props.dishes.dishes;
if(filter !== null){
// not sure if you call it storeName or something else, but filter the list
dishes = dishes.filter((dish) => dish.storeName === filter);
}
// and then do map with the filtered list
const menu = dishes.map((dish) => {
return (
<div key={dish.id} className="col-12 col-md-5 m-1">
<RenderMenuItem dish={dish} comments={props.comments.comments.filter((comments) => comments.dishId === dish.id)} />
</div>
);
});
...
I hope this helps!
When I write this code I have an error:
React Hook "useRef" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
What should I do with this code?
return ITEMS.map((item, i) => {
const elementRef = useRef(null);
return (
<div
ref={elementRef}
key={i}
>
<p>{item.name}</p>
<Wrapper>
{item.name === visibleItem && (
<Item
parentRef={elementRef}
/>
)}
</Wrapper>
</div>
);
}
Here are two possibilities, Either using useRef with an object/array, or using createRef as suggested by Yevgen Gorbunkov.
I'm not entirely sure as to the viability of these as the createRef option will create entirely new refs on each render, and the useRef option you'll need to make sure your keys/indexes are always the same.
const ITEMS = [{ name: "test" }, { name: "test2" }];
export default function App() {
const ref = useRef({});
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{ITEMS.map((item, idx) => {
return (
<div key={idx} ref={element => (ref.current[idx] = element)}>
<p>{item.name}</p>
<Wrapper>
{item.name === visibleItem && (
<Item parentRef={ref.current[idx]} />
)}
</Wrapper>
</div>
);
})}
{ITEMS.map((item, idx) => {
const ref = createRef();
return (
<div key={idx} ref={ref}>
<p>{item.name}</p>
<Wrapper>
{item.name === visibleItem && <Item parentRef={ref} />}
</Wrapper>
</div>
);
})}
</div>
);
}