I am trying to change a parent's component state from a child component's state.
This is the parent component:
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
selectedLanguage: 'EU',
repos: null,
error: null,
loggedin: false
}
this.updateLanguage = this.updateLanguage.bind(this)
this.logIn = this.logIn.bind(this)
}
componentDidMount () {
this.updateLanguage(this.state.selectedLanguage)
}
updateLanguage (selectedLanguage) {
this.setState({
selectedLanguage,
error: null
})
fetchLanguageRepos(selectedLanguage)
.then(
(repos) => this.setState({
repos,
error: null,
})
)
.catch(() => {
console.warn('Error fetching repos: ', error)
this.setState({
error: 'There was an error fetching the repositories.'
})
})
}
logIn() {
this.setState({
loggedin: true
})
}
render() {
const { selectedLanguage, repos, error, loggedin } = this.state
console.log(loggedin)
return (
<Router>
<div className='container'>
<LanguagesNav
selected={selectedLanguage}
onUpdateLanguage={this.updateLanguage}
/>
<Route
exact path='/'
render={(props) => (
<Login
repos={repos}
selectedLanguage={selectedLanguage}
logIn={this.logIn}
/>
)}
/>
<Route
path='/dashboard'
render={(props) => (
<Dashboard
repos={repos}
selectedLanguage={selectedLanguage}
/>
)}
/>
<Route
path='/profile'
render={(props) => (
<Profile
repos={repos}
selectedLanguage={selectedLanguage}
/>
)}
/>
<Route path='/newdashboard'>
<DrawerPage />
</Route>
</div>
</Router>
)
}
}
As I saw on this answer to a similar question, I am passing a function setting the state from parent to child, and then, I call the function via props from the child component:
function LoginForm ({ repos, selected }) {
const languages = ['EU', 'ES', 'EN']
var language = {}
switch (selected) {
case "EU":
selected = "EU";
language = repos[0].terms;
break;
case "ES":
selected = "ES";
language = repos[1].terms;
break;
case "EN":
selected = "EN";
language = repos[2].terms;
break;
}
return (
<ThemeProvider theme={theme}>
<Grid container component="main" sx={{ height: '100vh' }}>
<CssBaseline />
<Grid
item
xs={false}
sm={4}
md={7}
sx={{
backgroundImage: 'url(https://loginsso.ehu.es/login/images/forest.jpg)',
backgroundRepeat: 'no-repeat',
backgroundColor: (t) =>
t.palette.mode === 'light' ? t.palette.grey[50] : t.palette.grey[900],
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
/>
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<Box
sx={{
my: 8,
mx: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<img
src="https://loginsso.ehu.es/login/images/logo_UPV_peq.png"
/>
<br/>
<Box component="form" noValidate sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="email"
label={language.username}
name="email"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label={language.password}
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label={language.remember}
/>
<Link
to={{
pathname: '/dashboard',
search: `?lang=${selected}`
}}
>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
// onClick={() => {
// alert('clicked');
// }}
>
{language.login}
</Button>
</Link>
<Grid container>
<Grid item xs>
<Link
to={{
pathname: '/newdashboard',
search: `?lang=${selected}`
}} variant="body2">
{language.forgot}
</Link>
</Grid>
<Grid item>
</Grid>
</Grid>
</Box>
</Box>
</Grid>
</Grid>
</ThemeProvider>
)
}
LoginForm.propTypes = {
repos: PropTypes.array.isRequired
}
export default class Login extends React.Component {
constructor(props) {
super(props)
this.state = {
selectedLanguage: 'EU',
repos: null,
error: null,
}
this.updateLanguage = this.updateLanguage.bind(this)
}
componentDidMount () {
this.updateLanguage(this.state.selectedLanguage)
}
updateLanguage (selectedLanguage) {
this.setState({
selectedLanguage,
error: null
})
fetchLanguageRepos(selectedLanguage)
.then(
(repos) => this.setState({
repos,
error: null,
})
)
.catch(() => {
console.warn('Error fetching repos: ', error)
this.setState({
error: 'There was an error fetching the repositories.'
})
})
}
render() {
const { selectedLanguage, repos, error } = this.props
return (
<React.Fragment>
{this.props.logIn} //calling the parent's function
{error && <p>{error}</p>}
{repos && <LoginForm repos={repos} selected={selectedLanguage}/>}
</React.Fragment>
)
}
}
However, the state won't change.