大家好
我是这个 react-native 的新手,我正在尝试让 react-native、react router 4 和 firebase auth 工作。我想做的是检查用户是否已登录。如果他们已登录,它将显示“splash”组件,如果未登录,它将重定向到“/login”屏幕。
我确实关注了 react router 4 auth文档,但我无法让它工作。现在我确实想知道我在这里遗漏了什么,是否有人可以向我解释这一点,以便我理解为什么它不起作用。
这是我要实现的流程:
- 用户可以在未授权时导航到“/login”和“/register”
- 如果未授权,用户无法导航到“/”
- 当用户被授权时,他们将转到“/”并且组件“splash”附加到该路径
- 组件“splash”具有受 HOC 保护的嵌套路由
我正在为我的项目使用 create-react-native-app,这是我的文件。
app.js(根组件)
export default class App extends React.Component {
constructor() {
super();
this.state = {
isAuth: false,
email: "",
password: ""
};
}
onHandleLogin = (e, type) => {
const event = e.nativeEvent.text;
this.setState({ [type]: event });
};
onSubmitLogin = () => {
const email = this.state.email;
const password = this.state.password;
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.catch(err => {
console.log("error:", err);
});
};
isLoggedIn = () => {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.setState({ isAuth: true });
return true;
} else {
this.setState({ isAuth: false });
return false;
}
});
};
componentDidMount() {
this.isLoggedIn();
}
render() {
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
this.isLoggedIn() ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
return (
<NativeRouter>
<View style={styles.container}>
<Switch>
<Route
path="/login"
render={props => (
<Login
{...props}
submitFunc={this.onSubmitLogin}
login={this.onHandleLogin}
msg={this.state.isAuth}
/>
)}
/>
<Route path="/register" component={Register} />
<PrivateRoute path="/" component={Splash} />
</Switch>
</View>
</NativeRouter>
);
}
}
飞溅.js
import Home from "./../Home/Home";
const Splash = () => {
return (
<View style={styles.container}>
<Route exact path="/" component={Home} />
</View>
);
};
登录.js
const Login = ({ login, submitFunc }) => {
return (
<KeyboardAwareScrollView
resetScrollToCoords={{ x: 0, y: 0 }}
contentContainerStyle={styles.formContainer}
>
<InputContainer style={styles.inputContainer}>
<Logo source={logo} />
<Input
inputStyle={styles.input2}
onChange={e => login(e, "email")}
placeholder="Email"
clearButtonMode="always"
containerStyle={styles.input}
leftIcon={
<Icon
containerStyle={styles.iconContainer}
name="at"
size={20}
type="font-awesome"
color="#b2b2b2"
/>
}
/>
<Input
inputStyle={styles.input2}
onChange={e => login(e, "password")}
placeholder="Password"
clearButtonMode="always"
containerStyle={styles.input}
secureTextEntry={true}
leftIcon={
<Icon
containerStyle={styles.iconContainer}
name="lock"
size={20}
type="font-awesome"
color="#b2b2b2"
/>
}
/>
<Button
title="Log in"
buttonStyle={styles.button}
titleStyle={styles.buttonTitle}
onPress={() => submitFunc()}
/>
<Button
title="Forgot your password?"
buttonStyle={styles.buttonLink}
titleStyle={styles.buttonLinkTitle}
/>
<ForgotContainer>
<Text style={styles.text}>Don't have an account? </Text>
<Link component={TouchableOpacity} to="/register">
<Text>Create one</Text>
</Link>
</ForgotContainer>
</InputContainer>
</KeyboardAwareScrollView>
);
};
我很感激我能得到的所有帮助和解释,谢谢你们先进
最佳答案
根据 firebase documentation , onAuthStateChanged
添加一个监听器/观察器并返回一个非空函数():观察器的取消订阅函数。。
onAuthStateChanged(nextOrObserver, error, completed) returns function()
看看你的代码,有两件事你做错了
- 再次在
PrivateRoute
组件上重新初始化监听器,该组件不执行任何操作。 - 不
取消订阅
监听器,这可能会反过来增加额外开销,每当整个应用的身份验证状态发生变化
最佳方法是按如下方式进行:
componentDidMount() {
// Bind the variable to the instance of the class.
this.authFirebaseListener = firebase.auth().onAuthStateChanged((user) => {
this.setState({
loading: false, // For the loader maybe
user, // User Details
isAuth: true
});
});
}
componentWillUnmount() {
this.authFirebaseListener && this.authFirebaseListener() // Unlisten it by calling it as a function
}
在你的 PrivateRoute
组件中,使用 this.state
const PrivateRoute = ({ component: Component, isAuth, ...rest }) => ( // Pass it as a prop where your component is injected
<Route
{...rest}
render={props =>
isAuth ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
和
<PrivateRoute path="/" isAuth={this.state.isAuth} component={Splash} />
关于javascript - 状态更改授权组件后, native 渲染 View 不会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49608682/