Tenho vários componentes que precisam fazer a mesma coisa. (Uma função simples que mapeia seus componentes filhos e faz algo para cada um). No momento estou definindo este método em cada um dos componentes. Mas só quero definir uma vez.
Eu poderia defini-lo no componente de nível superior e depois passá-lo para baixo como um adereço. Mas isso não parece muito certo. É mais uma função de biblioteca do que um acessório. (Parece para mim).
Qual é a maneira correta de fazer isso?
Respostas:
Se você usar algo como o browserify , poderá ter um arquivo externo, ou seja, util.js, que exporta algumas funções do utilitário.
var doSomething = function(num) { return num + 1; } exports.doSomething = doSomething;
Em seguida, solicite conforme necessário
var doSomething = require('./util.js').doSomething;
fonte
Utils.js com a sintaxe Javascript ES6 mais recente
Crie o
Utils.js
arquivo assim com várias funções, etc.const someCommonValues = ['common', 'values']; export const doSomethingWithInput = (theInput) => { //Do something with the input return theInput; }; export const justAnAlert = () => { alert('hello'); };
Em seguida, nos componentes em que deseja usar as funções utilitárias, importe as funções específicas necessárias. Você não tem que importar tudo
import {doSomethingWithInput, justAnAlert} from './path/to/utils.js/file'
Em seguida, use essas funções dentro do componente como este:
justAnAlert(); <p>{doSomethingWithInput('hello')}</p>
fonte
/file
no final da linha de importação?Se você deseja manipular o estado em funções auxiliares, siga isto:
Crie um arquivo Helpers.js:
export function myFunc(){ return this.state.name; //define it according to your needs }
Importar função auxiliar em seu arquivo de componente:
import {myFunc} from 'path-to/Helpers.js'
Em seu construtor, adicione essa função auxiliar à classe
constructor(){ this.myFunc = myFunc.bind(this) }
Em sua função de renderização, use-o:
render(){ <div>{this.myFunc()}</div> }
fonte
Aqui estão alguns exemplos de como você pode reutilizar uma função (
FetchUtil.handleError
) em um componente React (App
).Solução 1: usando a sintaxe do módulo CommonJS
module.exports = { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, };
Solução 2: usando "createClass" (React v16)
util / FetchUtil.js
const createReactClass = require('create-react-class'); const FetchUtil = createReactClass({ statics: { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, }, render() { }, }); export default FetchUtil;
Observação: se você estiver usando o React v15.4 (ou inferior), será necessário importar da
createClass
seguinte forma:import React from 'react'; const FetchUtil = React.createClass({});
Fonte: https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-reactcreateclass
Componente (que reutiliza FetchUtil)
componentes / App.jsx
import Categories from './Categories.jsx'; import FetchUtil from '../utils/FetchUtil'; import Grid from 'material-ui/Grid'; import React from 'react'; class App extends React.Component { constructor(props) { super(props); this.state = {categories: []}; } componentWillMount() { window .fetch('/rest/service/v1/categories') .then(FetchUtil.handleError) .then(response => response.json()) .then(categories => this.setState({...this.state, categories})); } render() { return ( <Grid container={true} spacing={16}> <Grid item={true} xs={12}> <Categories categories={this.state.categories} /> </Grid> </Grid> ); } } export default App;
fonte
Outra opção sólida diferente de criar um arquivo util seria usar um componente de ordem superior para criar um
withComponentMapper()
wrapper. Este componente pegaria um componente como parâmetro e o retornaria com ocomponentMapper()
função passada como um suporte.Isso é considerado uma boa prática no React. Você pode descobrir como fazer isso em detalhes aqui.
fonte
Parece uma função de utilitário, nesse caso, por que não colocá-lo em um módulo de utilitário estático separado?
Caso contrário, se estiver usando um transpiler como o Babel, você pode usar os métodos estáticos do es7:
class MyComponent extends React.Component { static someMethod() { ...
Ou então, se você estiver usando React.createClass, poderá usar o objeto estático :
var MyComponent = React.createClass({ statics: { customMethod: function(foo) { return foo === 'bar'; } }
No entanto, não aconselho essas opções, não faz sentido incluir um componente para um método utilitário.
Além disso, você não deve passar um método por todos os seus componentes como um suporte, pois isso os unirá firmemente e tornará a refatoração mais dolorosa. Aconselho um módulo de utilitário simples e antigo.
A outra opção é usar um mixin para estender a classe, mas não recomendo, pois você não pode fazer isso no es6 + (e não vejo benefício neste caso).
fonte
React.createClass
está obsoleto desde React 15.5.0. O create-react-app sugere o uso do módulo npmcreate-react-class
.doSomething.js
, por exemplo , ou um arquivo com várias funções "utilitárias" semelhantes, por exemplo,utils.js
e importaria essas funções onde você precisa usá-lasMostrarei dois estilos abaixo e você vai querer escolher dependendo de quanto a lógica dos componentes se relaciona entre si.
Estilo 1 - Os componentes relacionados podem ser criados com referências de retorno de chamada, como este, em
./components/App.js
...<SomeItem ref={(instance) => {this.childA = instance}} /> <SomeOtherItem ref={(instance) => {this.childB = instance}} />
E então você pode usar funções compartilhadas entre eles assim ...
this.childA.investigateComponent(this.childB); // call childA function with childB as arg this.childB.makeNotesOnComponent(this.childA); // call childB function with childA as arg
Estilo 2 - os componentes do tipo utilitário podem ser criados assim, em
./utils/time.js
...export const getTimeDifference = function (start, end) { // return difference between start and end }
E então eles podem ser usados assim, em
./components/App.js
...import React from 'react'; import {getTimeDifference} from './utils/time.js'; export default class App extends React.Component { someFunction() { console.log(getTimeDifference("19:00:00", "20:00:00")); } }
Qual usar?
Se a lógica for relativamente relacionada (eles só são usados juntos no mesmo aplicativo), você deve compartilhar estados entre os componentes. Mas se a sua lógica for remotamente relacionada (ou seja, utilitário matemático, utilitário de formatação de texto), então você deve criar e importar funções de classe util.
fonte
Você não deveria usar um Mixin para isso? Veja https://facebook.github.io/react/docs/reusable-components.html
Embora estejam caindo em desgraça, consulte https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
Pode ser útil
fonte