如何调用组件类render方法中的函数方法?出现 Uncaught TypeError: 无法读取属性“值” React 中的 null
我正在使用组件和功能组件创建一个 Web 应用程序。我使用组件类创建了 Regsiter
和 Login
,但我很难使用组件类创建 Searchbar
,因此我使用函数组件创建了它。我很困惑我应该在哪里调用搜索功能?当函数本身只是一个函数组件时,它本身运行没有问题,并且我没有任何用于注册或登录的代码,所以我没有相信错误与函数本身有关。但是,当我添加 Register
和 Login
的代码并从渲染中调用该函数时,它似乎不起作用并返回为 null,有什么我遗漏的吗?我是否可能应该使用 componentDidMount()
做一些事情?
import React, { Component, useState } from "react";
import axios from 'axios';
import { Switch, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import styled from "styled-components";
import AuthService from "./services/auth.service";
import Login from "./components/login.component";
import Register from "./components/register.component";
import Home from "./components/home.component";
import Profile from "./components/profile.component";
import BoardUser from "./components/board-user.component";
import BoardCreator from "./components/board-creator.component";
import BoardAdmin from "./components/board-admin.component";
import MovieList from "./components/movie-list.component";
// import AuthVerify from "./common/auth-verify";
import EventBus from "./common/EventBus";
const Container = styled.div`
display: flex;
flex-direction: column;
`;
const AppName = styled.div`
display: flex;
flex-direction: row;
align-items: center;
`;
const Header = styled.div`
background-color: black;
color: white;
display: flex;
justify-content: space-between;
flex-direction: row;
align-items: center;
padding: 10px;
font-size: 25px;
font-weight: bold;
box-shadow: 0 3px 6px 0 #555;
`;
const SearchBox = styled.div`
display: flex;
flex-direction: row;
padding: 10px 10px;
border-radius: 6px;
margin-left: 20px;
width: 50%;
background-color: white;
`;
const SearchInput = styled.input`
color: black;
font-size: 16px;
font-weight: bold;
border: none;
outline: none;
margin-left: 15px;
`;
const MovieListContainer = styled.div`
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding: 30px;
gap: 25px;
justify-content: space-evenly;;
`;
class App extends Component {
constructor(props) {
super(props);
this.logOut = this.logOut.bind(this);
this.state = {
showCreatorBoard: false,
showAdminBoard: false,
currentUser: undefined,
timeoutId: "",
updateTimeoutId: ""
};
}
componentDidMount() {
const user = AuthService.getCurrentUser();
if (user) {
this.setState({
currentUser: user,
showCreatorBoard: user.roles.includes("ROLE_MODERATOR"),
showAdminBoard: user.roles.includes("ROLE_ADMIN"),
});
}
EventBus.on("logout", () => {
this.logOut();
});
}
componentWillUnmount() {
EventBus.remove("logout");
}
logOut() {
AuthService.logout();
this.setState({
showCreatorBoard: false,
showAdminBoard: false,
currentUser: undefined,
});
}
render() {
const { currentUser, showCreatorBoard, showAdminBoard} = this.state;
return (
<div>
<nav className="navbar navbar-expand navbar-dark bg-dark">
<Link to={"/"} className="navbar-brand">
Movie App
</Link>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/home"} className="nav-link">
Home
</Link>
</li>
{showCreatorBoard && (
<li className="nav-item">
<Link to={"/mod"} className="nav-link">
Moderator Board
</Link>
</li>
)}
{showAdminBoard && (
<li className="nav-item">
<Link to={"/admin"} className="nav-link">
Admin Board
</Link>
</li>
)}
{currentUser && (
<li className="nav-item">
<Link to={"/user"} className="nav-link">
User
</Link>
</li>
)}
</div>
<Search />
{currentUser ? (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/profile"} className="nav-link">
{currentUser.username}
</Link>
</li>
<li className="nav-item">
<a href="/login" className="nav-link" onClick={this.logOut}>
LogOut
</a>
</li>
</div>
) : (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/register"} className="nav-link">
Sign Up
</Link>
</li>
</div>
)}
</nav>
<div className="container mt-3">
<Switch>
<Route exact path={["/", "/home"]} component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profile" component={Profile} />
<Route path="/films"
component={MovieList}
/>
<Route path="/user" component={BoardUser} />
<Route path="/creator" component={BoardCreator} />
<Route path="/admin" component={BoardAdmin} />
</Switch>
</div>
<MovieListContainer>
<MovieList></MovieList>
<MovieList></MovieList>
<MovieList></MovieList>
<MovieList></MovieList>
</MovieListContainer>
{ /*<AuthVerify logOut={this.logOut}/> */ }
</div>
);
}
}
搜索
function Search() {
const [searchQuery, setSearchQuery] = useState("");
const [timeoutId, updateTimeoutId] = useState();
const fetchData = async (searchString) => {
const response = await axios.get(`https://api.themoviedb.org/3/search/movie?api_key=f134dfeac1ebb17feefa58d7f94e94cd&language=en-US&query=${searchString}&page=1&include_adult=false`);
console.log(response);
};
const onTextChange = (e) => {
clearTimeout(timeoutId);
setSearchQuery(e.target.value);
const timeout = setTimeout(() => fetchData(e.target.value), 500);
updateTimeoutId(timeout);
};
return(
<div>
<SearchBox>
<SearchInput placeholder="SEARCH" value={searchQuery} onChange={onTextChange}></SearchInput>
</SearchBox></div>
);
}
export default App;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
假设您使用的是 React 16 或更早版本,问题出在这一行:
直到最近,React 都尝试重用事件对象,因此一旦同步代码运行完毕,它会将 e.target 设置为 null。因此,当超时结束时,
e.target
为 null,因此e.target.value
会引发异常。选项 1:将值保存在局部变量中并使用该
选项 2:告诉 React 不要重用此事件对象
有关更多信息,查看此页面
Assuming you're on react 16 or earlier, the problem is this line:
Up until recently, react tried to reuse event objects, so it would set e.target to null once synchronous code is done running. As a result, by the time the timeout goes off,
e.target
is null, soe.target.value
throws an exception.Option 1: save the value in a local variable and use that
Option 2: tell react to not reuse this event object
For more information, see this page