提供渲染功能时,React不重新渲染道具

时间:2017-12-10 12:34:23

标签: javascript reactjs redux react-redux

我有理解为什么在提供渲染功能时不会发生渲染,而不是直接返回JSX。

这是我的InputBox组件示例:

export default React => {
  const InputBox = ({ city, setCity, setTime }) => {
    const onInputEnter = createOnInputEnter({ city, setCity, setTime, getCityTime })

    return (
        <div className='InputBox'>
          <input
            defaultValue={city}
            onKeyPress={onInputEnter}
            onFocus={moveFocusAtEnd}
            autoFocus />
        </div>
      )
  }

  return InputBox
}

在这种情况下,每当我改变城市的redux状态时都会重新呈现城市。

export default React => {
  const InputBox = ({ city, setCity, setTime }) => {
    const onInputEnter = createOnInputEnter({ city, setCity, setTime, getCityTime })

    const componentDidMount = async () => {
      const { city: resultCity, time: resultTime } = await getCityTime(city)

      setCity(resultCity)
      setTime(resultTime)
    }

    const render = () => {
      return (
        <div className='InputBox'>
          <input
            defaultValue={city}
            onKeyPress={onInputEnter}
            onFocus={moveFocusAtEnd}
            autoFocus />
        </div>
      )
    }

    return { render, componentDidMount }
  }

  return InputBox
}

在此示例中,city仅传递一次,并且在redux状态更改时不会重新呈现。

我想使用后面的例子,因为我使用componentDidMount方法进行初始化。

我在这个例子中使用了React和React-Redux。

这是我的InputBox容器的样子:

import createInputBox from '../components/InputBox.js'
import { connect } from 'react-redux'

...

export default React => {
  const InputBox = createInputBox(React)

  const InputBoxWithReduxStore = connect(
    ({ city }) => ({ city }),
    mapDispatchToProps
  )(InputBox)

  return InputBoxWithReduxStore
}

编辑:

我包含代码片段以显示createOnInputEnter函数的实现

function createOnInputEnter ({ city, setCity, setTime, getCityTime }) {
  return async ({ key, target }) => {
    if (key === 'Enter') {
      try {
        const inputCity = target.value

        setTime('...')

        const { city: resultCity, time: resultTime } = await getCityTime(inputCity)

        setCity(resultCity)
        setTime(resultTime)
      } catch (err) {
        const { city: resultCity, time: resultTime } = await getCityTime(city)

        setCity(resultCity)
        setTime(resultTime)
      }
    }
  }
}

由于@zarcode建议使用React.Component,因此不符合我的要求。因为我使用无类组件。更多关于Mixin部分:https://gist.github.com/jquense/47bbd2613e0b03d7e51c

3 个答案:

答案 0 :(得分:1)

componentDidMount只会调用一次,也可以自下而上调用。 因此,对于每个状态更改中的渲染,您可以使用componentWillReceieveprops。

答案 1 :(得分:1)

您的第一个示例是一个功能组件,如果您不需要组件生命周期方法(如componentDidMount),则可以使用该组件。

你的第二个例子是功能组件与生命周期方法的混合,不确定它是否可行,从未尝试过。 相反,如果您想在组件中使用生命周期方法,我建议您使用扩展React.Component的类组件。看起来应该是这样的:

...
import {Component} from "react";

export default class InputBox extends Component {
   onInputEnter = () => { 
       const { city, setCity, setTime } = this.props;
       createOnInputEnter({ city, setCity, setTime, getCityTime })
   }

   async componentDidMount() {
     const { city, setCity, setTime } = this.props;
     const { city: resultCity, time: resultTime } = await getCityTime(city)

     setCity(resultCity)
     setTime(resultTime)
   }

   render(){
     return (
       <div className='InputBox'>
         <input
           defaultValue={city}
           onKeyPress={onInputEnter}
           onFocus={moveFocusAtEnd}
           autoFocus />
       </div>
     )
   }

}

答案 2 :(得分:0)

在第一种情况下const onInputEnter = createOnInputEnter({ city, setCity, setTime, getCityTime })位于组件的render方法内部,因为它是一个功能组件。

我不知道这个概念是如何工作的,但是第二个例子与第一个例子相同,你需要做这样的事情:

export default React => {
  const InputBox = ({ city, setCity, setTime }) => {

    const componentDidMount = async () => {
      const { city: resultCity, time: resultTime } = await getCityTime(city)

      setCity(resultCity)
      setTime(resultTime)
    }

    const render = () => {
    const { city, setCity, setTime } = this.props;
    const onInputEnter = createOnInputEnter({ city, setCity, setTime, getCityTime })
      return (
        <div className='InputBox'>
          <input
            defaultValue={city}
            onKeyPress={onInputEnter}
            onFocus={moveFocusAtEnd}
            autoFocus />
        </div>
      )
    }

    return { render, componentDidMount }
  }

  return InputBox
}

虽然我不确定这是否可以在此处访问渲染中的道具。

相关问题