标签: react-hooks

在React中使用钩子创建事件处理程序的正确方法?

在典型的基于类的React组件中,这就是创建事件处理程序的方式:

class MyComponent extends Component {
  handleClick = () => {
    ...
  }

  render() {
    return <button onClick={this.handleClick}>Click Me</button>;
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我使用基于钩子的功能范例时,发现有两个选择:

const MyComponent = () => {
  const [handleClick] = useState(() => () => {
    ...
  });

  return <button onClick={handleClick}>Click Me</button>;
};
Run Code Online (Sandbox Code Playgroud)

或者:

const MyComponent = () => {
  const handleClick = useRef(() => {
    ...
  });

  return <button onClick={handleClick.current}>Click Me</button>;
};
Run Code Online (Sandbox Code Playgroud)

客观上哪个更好,出于什么原因?还有我还没有听说过的(更好)方法吗?

谢谢您的帮助。

编辑:我在CodeSandbox上放了一个示例显示了这两种方法。正如您从那里的代码可以看到的那样,似乎都没有必要在每个渲染器上重新创建事件处理程序,因此,我认为不可能出现性能问题。

javascript jsx reactjs react-hooks

21
推荐指数
1
解决办法
6073
查看次数

在打字稿中将 useState 作为道具传递

假设我有一个带有两个子组件的父组件:

const Parent = () => {
   const [myVar, setmyVar] = useState(false)

   return (
     <>
       <MyChildComponent1 myVar={myVar} setMyVar={setMyVar} \> 
       <MyChildComponent2 myVar={myVar} \>
     </>
   )
}
Run Code Online (Sandbox Code Playgroud)

现在我将如何正确设置类型MyChildComponent2

这是我到目前为止想出的:

const MyChildComponent1 = (
  {myVar, setMyVar}: 
  {myVar: boolean, setMyVar: (value: boolean) => void}) = (...)
Run Code Online (Sandbox Code Playgroud)

类型是否setMyvar正确?或者应该是别的什么?

typescript reactjs react-props react-hooks

21
推荐指数
3
解决办法
2万
查看次数

使用 React Hooks 更新带滚动

我试图根据个人是否在组件上向下滚动来控制 React 组件的可见性。可见性Fade作为“in”属性传递到元素中。

我已经使用 UseEffect Hook 设置了一个侦听器,它添加了 onMount 侦听器。实际的 onScroll 函数应该更新 scrollTop 状态(它是到页面顶部的高度的当前值),然后是滚动状态(将事件的滚动到页面顶部与之前的状态进行比较,以及如果第一个大于第二个,则返回 true)。

但是,由于某种原因 setScrollTop 钩子不起作用,滚动状态继续保持在 0。

我究竟做错了什么?这是完整的组件:

export const Header = (props) => {

  const classes = useStyles();

  const [scrolling, setScrolling] = useState(false);
  const [scrollTop, setScrollTop] = useState(0);

  const onScroll = (e) => {
    setScrollTop(e.target.documentElement.scrollTop);
    setScrolling(e.target.documentElement.scrollTop > scrollTop);
  }

  useEffect(() => {
    window.addEventListener('scroll', onScroll);
  },[]);

  useEffect(() => {
    console.log(scrollTop);
  }, [scrollTop])

  return (
   <Fade in={!scrolling}>
      <AppBar className={classes.header} position="fixed">

  ....
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks

21
推荐指数
2
解决办法
3万
查看次数

useReducer 中第三个参数的目的是什么?

文档

[init, the 3d argument] 允许您提取用于计算 reducer 之外的初始状态的逻辑。这对于稍后响应动作重置状态也很方便。

和代码:

function init(initialCount) {
  return { count: initialCount };
}

function reducer(state, action) {
  switch (action.type) {
    ...
    case 'reset':
      return init(action.payload);
    ...
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  ...
}
Run Code Online (Sandbox Code Playgroud)

为什么我会在重用常量时这样做initialState

const initialState = {
  count: 5,
};

function reducer(state, action) {
  switch (action.type) {
    ...
    case 'reset':
      return initialState;
    ...
  }
}

function Counter({initialCount}) {
  const [state, dispatch] = useReducer(reducer, …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks use-reducer

21
推荐指数
3
解决办法
8264
查看次数

是否可以在 React 的 useEffect 中使用自定义钩子?

我有一个非常基本的自定义钩子,它接受一个路径并从 firebase 返回一个文档

import React, { useState, useEffect, useContext } from 'react';
import { FirebaseContext } from '../sharedComponents/Firebase';

function useGetDocument(path) {
    const firebase = useContext(FirebaseContext)
    const [document, setDocument] = useState(null)

    useEffect(() => {
        const getDocument = async () => {
            let snapshot = await firebase.db.doc(path).get()
            let document = snapshot.data()
            document.id = snapshot.id
            setDocument(document)
        }
        getDocument()
    }, []);

    return document
}

export default useGetDocument
Run Code Online (Sandbox Code Playgroud)

然后我使用 useEffect 作为 componentDidMount/constructor 来更新状态

useEffect(() => {
    const init = async () => {

      let docSnapshot …
Run Code Online (Sandbox Code Playgroud)

reactjs react-hooks

21
推荐指数
3
解决办法
3万
查看次数

React Hook useCallback 收到一个依赖项未知的函数。改为传递内联函数

考虑这个例子:

 let memoizedCb = React.useCallback(
    memoize((param) => () => someFunction(param)),
    []
  );
Run Code Online (Sandbox Code Playgroud)

哪里memoize来自外部库,例如“fast-memoize”。上面的代码给出了警告:

React Hook useCallback 收到一个依赖项未知的函数。改为传递内联函数

我发现这个线程,如果我们适应我的用例,会建议将此作为解决方案(如果我没有错的话):

const memoizedCb = React.useMemo(
  () => memoize((param) => () => someFunction(param)),
  []
);
Run Code Online (Sandbox Code Playgroud)

警告是关于什么的?为什么useMemo解决这个问题?

注意:someFunction在函数组件之外定义,因此不需要将其作为依赖项。

javascript reactjs react-hooks usecallback

21
推荐指数
3
解决办法
3万
查看次数

是否可以使用React中的useState()挂钩在组件之间共享状态?

我正在试验React中的新Hook功能.考虑到我有以下两个组件(使用React Hooks) -

const HookComponent = () => {
  const [username, setUsername] = useState('Abrar');
  const [count, setState] = useState();
  const handleChange = (e) => {
    setUsername(e.target.value);
  }

  return (
    <div>
      <input name="userName" value={username} onChange={handleChange}/>
      <p>{username}</p>
      <p>From HookComponent: {count}</p>
    </div>
  )
}


const HookComponent2 = () => {
  const [count, setCount] = useState(999);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

钩权利要求来解决的共享部件之间的有状态逻辑的问题,但我发现之间的状态HookComponentHookComponent2不共享.例如,countin 的改变HookComponent2 …

javascript reactjs react-hooks

20
推荐指数
4
解决办法
9670
查看次数

错误的React与事件侦听器挂钩行为

我正在玩React钩子并面临一个问题.当我尝试使用事件监听器处理的按钮来控制日志时,它显示错误的状态.

CodeSandbox: https ://codesandbox.io/s/lrxw1wr97m

  1. 点击"添加卡片"按钮2次
  2. 在第一张卡中,单击Button1并在控制台中看到有2张卡处于状态(正确行为)
  3. 在第一张卡片中,单击Button2(由事件监听器处理)并在控制台中看到状态中只有1张卡片(行为错误)

为什么它显示错误的状态?在第一张卡中,Button2应在控制台中显示2张卡.有任何想法吗?

import React, { useState, useContext, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

const CardsContext = React.createContext();

const CardsProvider = props => {
  const [cards, setCards] = useState([]);

  const addCard = () => {
    const id = cards.length;
    setCards([...cards, { id: id, json: {} }]);
  };

  const handleCardClick = id => console.log(cards);
  const handleButtonClick = id => console.log(cards);

  return (
    <CardsContext.Provider
      value={{ cards, addCard, handleCardClick, handleButtonClick }}
    >
      {props.children} …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks

20
推荐指数
4
解决办法
1万
查看次数

如何在使用useContext的React Hook时更改Context值

useContextReact 16.8+上使用钩子效果很好。您可以创建一个组件,使用该钩子并利用上下文值而不会出现任何问题。

我不确定的是如何将更改应用于Context Provider值。

1)useContext挂钩是否严格地是一种使用上下文值的方法?

2)是否有推荐的方法,使用React挂钩来更新子组件的值,然后该子组件将使用useContext带有此上下文的挂钩触发任何组件的组件重新渲染?

const ThemeContext = React.createContext({
  style: 'light',
  visible: true
});

function Content() {
  const { style, visible } = React.useContext(ThemeContext);

  const handleClick = () => {
    // change the context values to
    // style: 'dark'
    // visible: false
  }

  return (
    <div>
      <p>
        The theme is <em>{style}</em> and state of visibility is 
        <em> {visible.toString()}</em>
      </p>
      <button onClick={handleClick}>Change Theme</button>
    </div>
  )
};

function App() {
  return <Content />
};

const rootElement = …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-context react-hooks

20
推荐指数
2
解决办法
8023
查看次数

在 useEffect 2nd param 中使用对象而不必将其字符串化为 JSON

在 JS 中,两个对象不相等。

const a = {}, b = {};
console.log(a === b);
Run Code Online (Sandbox Code Playgroud)

所以我不能在useEffect(React hooks)中使用一个对象作为第二个参数,因为它总是被认为是假的(所以它会重新渲染):

const a = {}, b = {};
console.log(a === b);
Run Code Online (Sandbox Code Playgroud)

这样做(上面的代码),每次组件重新渲染时都会产生运行效果,因为每次都认为对象不相等。

我可以通过将对象作为 JSON 字符串化值传递来“破解”它,但这有点脏 IMO:

function MyComponent() {
  // ...
  useEffect(() => {
    // do something
  }, [myObject]) // <- this is the object that can change.
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做到这一点并避免不必要的效果调用?

旁注:对象具有嵌套属性。效果必须在此对象内的每个更改上运行。

javascript json reactjs react-hooks

20
推荐指数
1
解决办法
1万
查看次数