Som*_*ial 5 reactjs react-native
我正在尝试创建一个被分成多个部分的组件。
例如,在下面的示例代码中,我的目标是在维护状态的同时将表单和操作分开。这样,我可以创建一个基本的表单+操作按钮组件,然后在不同的页面上设置不同的样式。
import { useState } from 'react'
const FormBasic = ({ children }) => {
const [ text, setText ] = useState('')
const onSubmit = () => console.log("Submitting");
const onChange = (e) => {
console.log("Typing", e.target.value);
setText(e.target.value)
}
const Form = () => <textarea rows={4} onChange={onChange} value={text} />;
const Actions = () => <button onClick={onSubmit}>Some Buttons</button>;
return children({ Form, Actions });
};
export default FormBasic;
Run Code Online (Sandbox Code Playgroud)
然后我将以这种方式使用它(如下)。问题是 - 对于静态组件来说,一切都渲染得很好,但是一旦状态发生变化,您就会开始看到问题。
例如,当我输入<textarea />并onChanged被触发时,该函数会重新呈现,并且您会失去文本区域的焦点。所以最终你无法真正在文本区域中输入内容。
export default function App() {
return (
<FormBasic>
{({ Form, Actions }) => {
return (<React.Fragment>
<div style={{ border: '1px solid red'}}>
<Form />
</div>
<div style={{ border: '1px solid blue'}}>
<Actions />
</div>
</React.Fragment>)
}}
</FormBasic>
);
}
Run Code Online (Sandbox Code Playgroud)
我包括一个代码沙箱 - https://codesandbox.io/s/solitary-brook-nrrbf?file=/src/App.js
这种组件的实际使用可能会有疑问。实际上,我如何修改我的代码,以便我可以继续使用导出的textarea.
或者是否有其他形式的导出组件,以便我可以拆分它们并维护状态?
或者上面的风格到底可行吗?
PS:我已经使用了 context 和 redux,但我试图在这个例子中不使用它们。我试图保持简单。
解决您的问题的一种方法是:使用 React Context API,而不是传递textand作为 props 。setText
具体来说:
FormBasic将成为状态+上下文提供者。Form并将Actions成为上下文消费者。这是我想到的(CodeSandbox 上的工作示例):
(我对状态变量使用了更通用的名称来帮助本文的其他读者)。
import React from "react";
import { useState, useContext, createContext } from "react";
// create the context with some generic defaults
const StateContext = createContext({
state: "",
setState: v => v
});
// create the context hook
const useStateContext = () => useContext(StateContext);
// the textarea component
const Form = () => {
const { state, setState } = useStateContext();
const onChange = (e) => {
console.log("Typing", e.target.value);
setState(e.target.value);
};
return <textarea rows={4} onChange={onChange} value={state} />;
};
// the buttons component
const Actions = () => {
const { state } = useStateContext();
const onSubmit = () => {
alert(state);
};
return <button onClick={onSubmit}>Some Buttons</button>;
};
// the form itself holding state and the context provider
const FormBasic = ({ children }) => {
const [state, setState] = useState("");
return (
<StateContext.Provider value={{ state, setState }}>
{children}
</StateContext.Provider>
);
};
const App = () => {
return (
<FormBasic>
<div style={{ border: "1px solid red" }}>
<Form />
</div>
<div style={{ border: "1px solid blue" }}>
<Actions />
</div>
</FormBasic>
);
};
Run Code Online (Sandbox Code Playgroud)
请注意,FormBasic不再需要作为children函数或包装在 中的内容React.Fragment,使代码更清晰。您可以直接使用上下文消费者。
| 归档时间: |
|
| 查看次数: |
968 次 |
| 最近记录: |