目前我有一个useLazyQuery钩子,它在按下按钮时被触发(搜索表单的一部分)。
钩子行为正常,只有在按下按钮时才会触发。但是,一旦我触发它一次,它就会在每次组件重新渲染时触发(通常是由于状态更改)。
因此,如果我搜索一次,然后编辑搜索字段,结果会立即出现,而且我不必再次单击搜索按钮。
不是我想要的用户界面,如果您完全删除搜索文本(因为它试图将搜索文本null作为变量进行搜索),它会导致错误,有什么方法可以防止useLazyQuery在重新渲染时重新获取?
这可以使用useQuery依赖于“搜索”状态来解决,当我单击按钮时,该状态会被切换。但是,我宁愿看看是否可以避免增加组件的复杂性。
const AddCardSidebar = props => {
const [searching, toggleSearching] = useState(false);
const [searchParams, setSearchParams] = useState({
name: ''
});
const [searchResults, setSearchResults] = useState([]);
const [selectedCard, setSelectedCard] = useState();
const [searchCardsQuery, searchCardsQueryResponse] = useLazyQuery(SEARCH_CARDS, {
variables: { searchParams },
onCompleted() {
setSearchResults(searchCardsQueryResponse.data.searchCards.cards);
}
});
...
return (
<div>
<h1>AddCardSidebar</h1>
<div>
{searchResults.length !== 0 &&
searchResults.map(result => {
return (
<img
key={result.scryfall_id}
src={result.image_uris.small}
alt={result.name}
onClick={() => setSelectedCard(result.scryfall_id)}
/> …Run Code Online (Sandbox Code Playgroud) 我正在使用 Enzyme 的浅层方法来测试使用useParams钩子从 URL 参数中获取 ID的组件。
我试图模拟useParams钩子,使其不调用实际方法,但它不起作用。我仍然得到TypeError: Cannot read property 'match' of undefined,所以它调用了实际的useParams,而不是我的模拟。
我的组件:
import React from 'react';
import { useParams } from 'react-router-dom';
export default () => {
const { id } = useParams();
return <div>{id}</div>;
};
Run Code Online (Sandbox Code Playgroud)
测试:
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import Header from './header';
import { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
describe('<Header />', () => {
jest.mock('react-router-dom', …Run Code Online (Sandbox Code Playgroud) 我一直在研究编写自己的 React 钩子,但到目前为止,我一直在努力从技术层面说明普通 JavaScript 函数和钩子之间的区别。
例如,这篇文章说钩子是“普通的 JavaScript 函数,可以在其中使用其他钩子”,但在幕后还有什么?
我知道我们use在钩子名称中使用了这个词,但我很好奇钩子是什么使它们成为钩子而不是函数!
我正在使用 React Hooks - 重写表单以使用钩子概念。一切都按预期工作,除了一旦我在输入中输入任何 1 个字符,输入就会失去焦点。
我猜有一个问题,组件的外部不知道组件内部的变化,但是我该如何解决这个问题呢?
这是 useForm 钩子:
import React, { useState } from "react";
export default function useForm(defaultState, label) {
const [state, setState] = useState(defaultState);
const FormComponent = () => (
<form>
<label htmlFor={label}>
{label}
<input
type="text"
id={label}
value={state}
placeholder={label}
onChange={e => setState(e.target.value)}
/>
</label>
</form>
);
return [state, FormComponent, setState];
}
Run Code Online (Sandbox Code Playgroud)
这是使用 Hook 的组件:
function App() {
const [formValue, Form, setFormValue] = useForm("San Francisco, CA", "Location");
return (
<Fragment>
<h1>{formValue}</h1>
<Form />
</Fragment>
);
}
Run Code Online (Sandbox Code Playgroud) 我使用钩子在 React 组件中收集了一系列用户数据元素。
const [mobile, setMobile] = useState('');
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
Run Code Online (Sandbox Code Playgroud)
其中每一个更新如下。
<input type="text"
className="form-control"
id="mobile"
placeholder="Enter a valid mobile number"
onChange={event => {setMobile(event.target.value)}}/>
Run Code Online (Sandbox Code Playgroud)
使用对象作为变量有没有更简洁的方法来做到这一点?
如何能在useEffect钩(或任何其他挂钩的这个问题)可以被用来复制componentWillUnmount?
在传统的类组件中,我将执行以下操作:
class Effect extends React.PureComponent {
componentDidMount() { console.log("MOUNT", this.props); }
componentWillUnmount() { console.log("UNMOUNT", this.props); }
render() { return null; }
}
Run Code Online (Sandbox Code Playgroud)
随着useEffect钩:
function Effect(props) {
React.useEffect(() => {
console.log("MOUNT", props);
return () => console.log("UNMOUNT", props)
}, []);
return null;
}
Run Code Online (Sandbox Code Playgroud)
(完整示例:https : //codesandbox.io/s/2oo7zqzx1n)
这是行不通的,因为返回的“清理”功能会useEffect捕获安装过程中的道具,而不会在卸载过程中捕获道具的状态。
我怎么能获得最新版本的道具的useEffect清理,而不在每一个道具的变化运行的函数体(或清理)?
一个类似的问题没有解决获得最新道具的问题。
该反应文档状态:
如果要运行效果并仅将其清除一次(在挂载和卸载时),则可以传递一个空数组([])作为第二个参数。这告诉React您的效果不依赖于props或state的任何值,因此它不需要重新运行。
但是在这种情况下,我依赖道具...但仅用于清理部分...
更新的问题:
如果我在滚动之前在输入字段中输入某些内容,则expanded道具将设置为 true - 正确
如果我向下滚动 - 展开设置为 false - 正确
如果我现在在输入字段中输入expanded内容仍然是false- 我希望再次expanded设置为true。
代码:
export default () => {
const [expanded, setExpanded] = useState(true)
let searchInput = React.createRef()
let scrollTopValue = 0;
function handleSearchInput() {
console.log(Boolean(searchInput.current.value.length))
setExpanded(Boolean(searchInput.current.value.length)) // first time true, don't get re triggered
}
useEffect(() => {
window.addEventListener('scroll', handleScroll)
return () => window.removeEventListener('scroll', handleScroll)
}, []);
function handleScroll() {
setExpanded(scrollTopValue > document.documentElement.scrollTop)
scrollTopValue = document.documentElement.scrollTop
}
return ( …Run Code Online (Sandbox Code Playgroud) 我正在建造一个 <BasicForm>组件,用于在我的应用程序中构建表单。它应该处理提交、验证并且还应该跟踪输入状态(如触摸、脏等)。
因此,它需要一些函数来完成所有这些,我一直想知道放置这些声明的最佳位置是什么(关于代码组织和性能优化,考虑 React 和 JavaScript 最佳实践)。
我正在使用 React 16.8 钩子并与 Webpack 捆绑。
到目前为止,这是我所拥有的:
基本表单.js
/* I moved those validating functions to a different file
because I thought they are helpers and not directly related
to my BasicForm functionality */
import { validateText, validatePassword, validateEmail } from './Parts/ValidationHelpers';
function BasicForm(props) {
const [inputs, setInputs] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
// These are functions to handle these events
function onChange(event) {...}
function onBlur(event) {...}
function onFocus(event) {...}
// …Run Code Online (Sandbox Code Playgroud) 使用 Hooks/Functional 组件在 React 中优化和使代码更具可读性的更好方法是什么?每个组件有一个 setState 钩子还是多个?
为了扩展我的问题,请考虑以下内容:
使用钩子,我们可以使用多个状态,以某种方式更方便地拆分特定用途的状态(例如,一种状态用于用户数据,另一种用于保存加载标志,另一种用于为 API 检索的数据等) . 在我的第一步中,我确信最好的方法是每个我想要管理的数据都有多个状态……但是,一段时间后,当我想要时,我开始遇到多个状态之间的同步问题更新/读取效果函数中的多个状态(useEffect)。
所以,我开始相信使用 Hooks 管理状态的最佳方法它只有一个使用对象的状态并从这里管理我的所有数据......就像类组件......
const [data, setData] = useState({
retrieveData: false,
apiData: [],
userInfo: [],
showModal: false
})
// To update:
setData(oldData => {
return { ...oldData, showModal: true }
})
// Or:
setData({ ...data, retrieveData: true })
Run Code Online (Sandbox Code Playgroud)
在我看来,最好有一个状态,但这可能会以某种我没有考虑的方式影响性能/可读性?
每次我在 data prop 中获取新数据但组件在我调用之前不会重新渲染 handlePanelSelection()
function StepPanel({ data, getTranslations }) {
const [panelsData, changePanel] = useState(data);
function handlePanelSelection(panelId) {
switch (panelId) {
case 8:
changePanel(getTranslations.NeeSubCategory);
break;
default:
changePanel(data);
break;
}
}
return (
<>
{panelsData.map(details => {
const imgsrc = requireContext('./' + details.image);
return (
<div key={details.id} className="block-list">
<div className="left-block">
<img src={imgsrc} alt="" />
</div>
<div className="right-block">
<h3>{details.title}</h3>
<p>{details.description}</p>
<label htmlFor="radio1" className="radio-btn">
<input
type="radio"
onClick={() => handlePanelSelection(details.id)}
name="radio1"
/>
<span></span>
</label>
</div>
</div>
);
})}
</>
);
}
Run Code Online (Sandbox Code Playgroud)
但是当我像下面一样取下钩子时它就起作用了
function …Run Code Online (Sandbox Code Playgroud) react-hooks ×10
reactjs ×9
javascript ×6
apollo ×1
enzyme ×1
graphql ×1
jestjs ×1
react-apollo ×1
react-router ×1
typescript ×1