无状态组件中的功能?

时间:2017-09-10 07:02:06

标签: reactjs

我试图将我发现here的这个很酷的<canvas>动画转换为React可重用组件。看起来这个组件需要画布的一个父组件,以及function Ball()的许多子组件。

出于性能原因,将Balls变成无状态组件可能会更好,因为它们会有很多。我对制作无状态组件并不熟悉,并且想知道在哪里定义this.update()中定义的this.drawfunction Ball()函数。

无状态组件的功能是在组件内部还是外部?换句话说,以下哪个更好?

1:

const Ball = (props) => {
    const update = () => {
        ...
    }

    const draw = () => {
        ...
    }

    return (
       ...
    );
}

2:

function update() {
     ...
}

function draw() {
     ...
}

const Ball = (props) => {
    return (
       ...
    );
}

每个人的优缺点是什么?对于像我这样的具体用例,其中一个更好吗?

5 个答案:

答案 0 :(得分:36)

首先要注意的是无状态功能组件不能有方法,如果它是无状态函数,你不应该依赖于在渲染的update上调用drawBall成分

在大多数情况下,您应该在组件函数之外声明函数,因此您只声明它们一次并始终重用相同的引用。在内部声明函数时,每次渲染组件时,都会再次定义函数。

在某些情况下,您需要在组件内部定义一个函数,例如,将其指定为基于组件属性的行为不同的事件处理程序。但您仍然可以在Ball之外定义函数并将其与属性绑定,从而使代码更清晰,并使updatedraw函数可重用。

// You can use update somewhere else
const update (propX, a, b) => { ... };

const Ball = props => (
  <Something onClick={update.bind(null, props.x)} />
);

而不是:

const Ball = props => {
  function update(a, b) {
    // props.x is visible here
  }

  return (
    <Something onClick={update} />
  );
}

答案 1 :(得分:3)

我们可以在无状态功能组件中包含函数,下面是示例:

 const Action = () => {
  function  handlePick(){
     alert("test");
  }
  return (
    <div>
      <input type="button" onClick={handlePick} value="What you want to do ?" />
    </div>
  );
}

但是,这不是一个好习惯,因为每次调用该组件时都会定义函数handlePick()

答案 2 :(得分:0)

2:很好,但是当您想使用道具时却有悲剧。

最佳实践是useHooks函数,例如useCallback函数。

从反应库导入它们。

答案 3 :(得分:0)

我们可以在功能组件中如下使用React钩子useCallback

const home = (props) => {
    const { small, img } = props
    const [currentInd, setCurrentInd] = useState(0);
    const imgArrayLength = img.length - 1;
    useEffect(() => {
        let id = setInterval(() => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {
                setCurrentInd(0)
            }
        }, 5000);
        return () => clearInterval(id);
    }, [currentInd]);
    const onLeftClickHandler = useCallback(
        () => {
            if (currentInd === 0) {

            }
            else {
                setCurrentInd(currentInd => currentInd - 1)
            }
        },
        [currentInd],
    );

    const onRightClickHandler = useCallback(
        () => {
            if (currentInd < imgArrayLength) {
                setCurrentInd(currentInd => currentInd + 1)
            }
            else {

            }
        },
        [currentInd],
    );
    return (
        <Wrapper img={img[currentInd]}>
            <LeftSliderArrow className={currentInd > 0 ? "red" : 'no-red'} onClick={onLeftClickHandler}>
                <img src={Icon_dir + "chevron_left_light.png"}></img>
            </LeftSliderArrow>
            <RightSliderArrow className={currentInd < imgArrayLength ? "red" : 'no-red'} onClick={onRightClickHandler}>
                <img src={Icon_dir + "chevron_right_light.png"}></img>
            </RightSliderArrow>
        </Wrapper>);
}

export default home;

我从它的父级那里获取了'img',那是一个数组。

答案 4 :(得分:0)

import React, { useState } from 'react';
function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  const a = () => {
    setCount(count + 1);
  };
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={a}>Click me</button>
    </div>
  );
}
export default Example;