我有一个关于提升状态的问题,我知道他是这里的一个常见问题,但我希望有人会设法帮助我理解。
问题:我有一个由表单组件组成的登录组件,我在其中进行提取调用以执行登录。我想保留从fetch调用中获取的令牌并将其保存在App组件中,以便可以使用此令牌并将其传递给其他页面/组件。
那么,首先要从我的App.js /父组件中的代码开始?
在这里,我管理我的路线,这也是我要存储其状态的她。 我将令牌从此状态传递到Login组件,如呈现Login组件的Route所示。
从我读到的内容来看,道具不是可变的,所以这实际上不符合我的想法吗?我做了handleToken函数,但我会返回。
export default class App extends Component {
state = {
token: "",
regNo: "",
};
handleToken = (token) => {
this.setState({ token: token})
}
render() {
console.log(this.state.token);
return (
<Router >
<div>
<Header />
<Navbar isLoggedIn={this.state.token} />
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route path="/profile" render={() => <Profile userToken={this.state.token} />} />
<Route path="/login" render={() => <Login userToken={this.state.token} />} />
<Route path="/register" render={() => <Register />} />
<Route path="/carpage" render={() => <CarPage regNo={this.state.regNo} />} />
<Route path="/find-rental" render={() => <FindRental regNo={this.state.regNo} setRegno={this.setRegno}/>} />
<Route path="/rent-out-car" render={() => <RentOutCar />} />
<Route component={NoMatch} />
</Switch>
</div>
</Router >
);
};
现在,我们移至“登录”组件。该组件由组成登录页面的多个其他组件组成。其中之一是FormContainer,在其中进行登录的获取调用。
const Login = (props) => (
<Container fluid={true}>
<BrandRow>
</BrandRow>
<FormRow>
<FormContainer /* userToken={this.props.userToken} */ />
</FormRow>
</Container>
);
export default Login;
(不知道为什么它不能作为代码示例正确呈现,所以它进入了代码片段)
因此,如您在此登录组件中所见,我拥有FormContainer,它是所有操作发生的地方。
让我告诉你:
class FormContainer extends Component {
state = {
userName: '',
password: '',
};
handleChange = event => {
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({ [name]: value });
}
handleSubmit = event => {
event.preventDefault();
const credentials = { username: this.state.userName, password: this.state.password };
this.login(credentials);
}
login = credentials => {
const url = "https://fenonline.dk/SYS_Backend/api/login";
const postHeader = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(credentials)
};
fetch(url, postHeader).then(res => {
if (!res.ok) { throw Error(res.status + ": " + res.statusText + " | Wrong username or password!"); }
return res.json();
}).then(data => {
this.props.userToken = data.token;
alert("You have succesfully logged in!" + data.token);
this.props.history.push('/profile')
}).catch(error => alert(error));
}
render() {
const { userName, password } = this.state;
return (
<Container>
<Form onSubmit={this.handleSubmit}>
<Title>Sign In</Title>
<Input
type="text"
name="userName"
value={userName}
onChange={this.handleChange}
placeholder="Username.."
/>
<Input
type="password"
name="password"
value={password}
onChange={this.handleChange}
placeholder="Password.."
/>
<Button type="submit">Sign In</Button>
<Button onClick={() => this.props.history.push('/register')}>Register</Button>
</Form>
<Text>Rental service created by users for users.</Text>
</Container>
);
}
}
export default withRouter(FormContainer);
您要在这里查看的是登录功能,我在其中创建了fetch调用,这是我在其中获取要保存到其提升状态的令牌的地方。现在,我尝试通过说this.props.userToken = data.token进行设置;但是如果道具是永恒的,我该怎么做?
答案 0 :(得分:1)
为了将状态提升到顶级组件,您需要将handleToken
函数作为道具传递到登录组件中。
<Route path="/login" render={() => <Login userToken={this.state.token} handleToken={this.handleToken} />} />
然后,您还需要将其作为道具传递到FormContainer
组件中。
<FormContainer handleToken={this.props.handleToken} />
最后,在您的fetch
中,您需要在第二个.then()
中调用此方法,而不是尝试将令牌分配给prop
。
this.props.handleToken(data.token)
这将允许将状态提升到父级,然后将令牌作为prop
传递给您的其他组件。