[英]React Class Component Separate UI & Business Logic
I am trying to separate UI and Logic in React class component with little bit of js.我正在尝试使用少量 js 将 React class 组件中的 UI 和逻辑分开。 I know this could be done easily with custom hooks.
我知道这可以通过自定义挂钩轻松完成。 But I need to do with class components.
但我需要处理 class 个组件。
I could make some progress, but it doesnot seem efficient, need your input.我可以取得一些进展,但似乎效率不高,需要您的意见。
App.view.js
import React from "react";
import Header from "../components/Header";
import ListWrapper from "../components/ListWrapper";
import SearchField from "../components/SearchField";
import UserCard from "../components/UserCard";
import AppController from "./App.controller";
class App extends React.Component {
constructor() {
super();
this.state = { users: [], searchValue: "" };
this.setState = this.setState.bind(this);
}
componentDidMount() {
AppController(this.state, this.setState).fetchUsers();
}
render() {
const filteredUsers = AppController(
this.state,
this.setState
).handleFilter();
return (
<div className="wrapper pb-12 bg-gray-100 mx-auto max-w-7xl">
<Header heading="🐶 Pets Rolodex" />
<SearchField
labelText="Search Pets"
fieldId="pets-search-field"
placeholderText="Enter name"
searchValue={this.state.searchValue}
handleChange={AppController(this.state, this.setState).handleChange}
className="w-72"
/>
<ListWrapper
listData={filteredUsers}
ListItem={UserCard}
ListItemProp="user"
/>
</div>
);
}
}
export default App;
App.controller.js
const AppController = (state, setState) => ({
// Fetch Users info
fetchUsers: () => {
fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(data => setState({ users: data }))
.catch(error => console.error(error));
},
// Input Field Handler
handleChange: event => {
const { value } = event.target;
setState({ searchValue: value });
},
// Filter Handler
handleFilter: () => {
const { searchValue, users } = state;
if (searchValue === "") {
return users;
} else {
return users.filter(usr =>
usr.name.toLowerCase().includes(searchValue.toLowerCase())
);
}
}
});
export default AppController;
This works fine.这很好用。Codesandbox
代码沙盒
But the issue is, this instantiates multiple objects from function calls AppController(this.state, this.setState)
and this happens on every render(){...}
It is like I am creating and destroying function stored in memory.但问题是,这从 function 调用
AppController(this.state, this.setState)
实例化多个对象,这发生在每个render(){...}
就像我正在创建和销毁存储在 memory 中的 function。
I moved the function call to constructor like below:我将 function 调用移动到构造函数,如下所示:
constructor() {
super();
this.state = { users: [], searchValue: "" };
this.setState = this.setState.bind(this);
this.controller = AppController(this.state, this.setState)
}
and used this.controller
everywhere in view.并在视图中到处使用
this.controller
。
But this seems to persist initial state (empty) into function's execution context and all logic functions inside it never see a light of new state.但这似乎将初始 state(空)保留到函数的执行上下文中,并且其中的所有逻辑函数都看不到新的 state。
Thanks in advance for your input:)提前感谢您的输入:)
You can refactor the AppController
to class and pass the component instance to its constructor.您可以将
AppController
重构为 class 并将组件实例传递给其构造函数。
Eg例如
App.tsx
: App.tsx
:
import React from "react";
import ReactDOM from "react-dom";
import Controller from "./controller";
class App extends React.Component<any, { users: any[]; searchValue: string }> {
controller: InstanceType<typeof Controller>;
constructor(props) {
super(props);
this.state = { users: [], searchValue: "" };
this.controller = new Controller(this);
}
componentDidMount() {
this.controller.fetchUsers();
}
render() {
const filteredUsers = this.controller.handleFilter();
return (
<ul>
{filteredUsers.map((user) => (
<li key={user.key}>{user.name}</li>
))}
</ul>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
controller.ts
: controller.ts
:
class Controller {
compInstance;
constructor(compInstance) {
this.compInstance = compInstance;
}
// Fetch Users info
fetchUsers() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((data) => this.compInstance.setState({ users: data }))
.catch((error) => console.error(error));
}
// Input Field Handler
handleChange(event) {
const { value } = event.target;
this.compInstance.setState({ searchValue: value });
}
// Filter Handler
handleFilter() {
const { searchValue, users } = this.compInstance.state;
if (searchValue === "") {
return users;
} else {
return users.filter((usr) =>
usr.name.toLowerCase().includes(searchValue.toLowerCase())
);
}
}
}
export default Controller;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.