I've checked the previous answer on different topics about re-rendering but couldn't find a proper way to fix this. I am trying to re-render a ponent after the onChange event is fired on the select box.
I have a userlist with 5 users and I separated them into genders array. So I have a males array and a females array. I am trying to show the selected gender user list after the onChange event.
I tried to use the 'key' attr in ponent but it didn't work.
here is my UserList container:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import List from '../ponents/List.jsx'
class UserList extends Component {
constructor(props) {
super(props);
}
renderUser = (toMap) => {
console.log(toMap);
return (
<List key = {toMap.length} users = {toMap}/>
);
}
renderSelect = () => {
return (
<select id="gender" onChange={this.handleChange}>
<option value="select">Select a gender</option>
<option value="males">Males</option>
<option value="females">Females</option>
</select>
);
}
handleChange = (e) => {
const {userList,males,females} = this.props;
const gender = e.target.value;
if(gender == 'males'){
return this.renderUser(males);
}else if(gender == 'females'){
return this.renderUser(females);
}
return this.renderUser(userList);
}
render() {
const {isLoading,error,userList} = this.props;
return (
<div>
{this.renderSelect()}
<ul>
{this.renderUser(userList)}
</ul>
</div>
);
}
}
export default connect(mapStateToProps)(UserList);
here is my List Component:
import React from 'react';
const List = ({users}) => (
<ul>
{users.map( (user,index) => (
<li key = {index} >{user.email}</li>
))}
</ul>
);
export default List;
the props (users) are passing correctly when I check the console in handleChange but can't quite a visual result.
I've checked the previous answer on different topics about re-rendering but couldn't find a proper way to fix this. I am trying to re-render a ponent after the onChange event is fired on the select box.
I have a userlist with 5 users and I separated them into genders array. So I have a males array and a females array. I am trying to show the selected gender user list after the onChange event.
I tried to use the 'key' attr in ponent but it didn't work.
here is my UserList container:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import List from '../ponents/List.jsx'
class UserList extends Component {
constructor(props) {
super(props);
}
renderUser = (toMap) => {
console.log(toMap);
return (
<List key = {toMap.length} users = {toMap}/>
);
}
renderSelect = () => {
return (
<select id="gender" onChange={this.handleChange}>
<option value="select">Select a gender</option>
<option value="males">Males</option>
<option value="females">Females</option>
</select>
);
}
handleChange = (e) => {
const {userList,males,females} = this.props;
const gender = e.target.value;
if(gender == 'males'){
return this.renderUser(males);
}else if(gender == 'females'){
return this.renderUser(females);
}
return this.renderUser(userList);
}
render() {
const {isLoading,error,userList} = this.props;
return (
<div>
{this.renderSelect()}
<ul>
{this.renderUser(userList)}
</ul>
</div>
);
}
}
export default connect(mapStateToProps)(UserList);
here is my List Component:
import React from 'react';
const List = ({users}) => (
<ul>
{users.map( (user,index) => (
<li key = {index} >{user.email}</li>
))}
</ul>
);
export default List;
the props (users) are passing correctly when I check the console in handleChange but can't quite a visual result.
Share Improve this question asked Aug 15, 2019 at 8:51 Ekin AlcarEkin Alcar 1353 silver badges7 bronze badges 5-
1
You should store your selection in
state
. Your ponents will rerender after state changes. – Sasha Commented Aug 15, 2019 at 8:55 - 1 Hi Ekin, could you solve this issue ? – sebastienbarbier Commented Sep 12, 2019 at 12:19
- hi @sebastienbarbier yes I updated the state. – Ekin Alcar Commented Sep 12, 2019 at 17:49
- Awesome, please feel free to mark your question as answered when you have a moment :). Have a great day. – sebastienbarbier Commented Sep 13, 2019 at 10:44
- I am so sorry marked as accepted now! – Ekin Alcar Commented Sep 13, 2019 at 15:27
2 Answers
Reset to default 4State and Lifecycle
You should use state / setState as a way to trigger a rendering on react.
setState() enqueues changes to the ponent state and tells React that this ponent and its children need to be re-rendered with the updated state.
Main idea here is to store gender value in state, as we want to render when this value is changed
Add a initial state on your contructor
constructor(props) { super(props); this.state = { gender: [] } }
Update onChange event, using
setState()
with a new value. This function will notify asynchroniously react about the need to rerender. You need to refactor a bit your logic to clean you change handler with just updating state. Keep in mind setState is async, might be source of misunderstanding.handleChange = (e) => { setState({gender: e.target.value}); }
Final version should look something like this :
import React, { Component } from "react"; import ReactDOM from "react-dom"; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import List from '../ponents/List.jsx' class UserList extends Component { constructor(props) { super(props); this.state = { gender: null }; } renderUser = (toMap) => { return ( <List key = {toMap.length} users = {toMap.filter(user => this.state.gender ? user.gender === this.state.gender : true)}/> ); } renderSelect = () => { return ( <select id="gender" onChange={this.handleChange}> <option value="select">Select a gender</option> <option value="males">Males</option> <option value="females">Females</option> </select> ); } handleChange = (e) => { this.setState({ gender: e.target.value}) } render() { const {isLoading,error,userList} = this.props; return ( <div> { this.renderSelect() } <ul> { this.renderUser(userList) } </ul> </div> ); } }
renderUser()
will perform afilter
based on selected gender. No need to store males and females as performance should be fine for most case.
Here is a working example of your code : https://codesandbox.io/s/new-wkgu6
you are not setting state anywhere because of which ponent is not rendering again
setState() will always lead to a re-render unless shouldComponentUpdate() returns false.
More information on setState api can be found here
https://reactjs/docs/react-ponent.html#setstate