J'ai plusieurs composants qui doivent tous faire la même chose. (Une fonction simple qui mappe sur leurs composants enfants et fait quelque chose à chacun). En ce moment, je définis cette méthode dans chacun des composants. Mais je ne veux le définir qu'une seule fois.
Je pourrais le définir dans le composant de niveau supérieur, puis le transmettre comme accessoire. Mais cela ne semble pas tout à fait correct. C'est plus une fonction de bibliothèque qu'un accessoire. (Il me semble).
Quelle est la bonne façon de procéder?
Réponses:
Si vous utilisez quelque chose comme browserify, vous pouvez avoir un fichier externe ie util.js qui exporte certaines fonctions utilitaires.
var doSomething = function(num) { return num + 1; } exports.doSomething = doSomething;
Ensuite, exigez-le au besoin
var doSomething = require('./util.js').doSomething;
la source
Utils.js avec la dernière syntaxe Javascript ES6
Créez le
Utils.js
fichier comme celui-ci avec plusieurs fonctions, etc.const someCommonValues = ['common', 'values']; export const doSomethingWithInput = (theInput) => { //Do something with the input return theInput; }; export const justAnAlert = () => { alert('hello'); };
Ensuite, dans vos composants que vous souhaitez utiliser les fonctions util, importez les fonctions spécifiques nécessaires. Vous n'avez pas à tout importer
import {doSomethingWithInput, justAnAlert} from './path/to/utils.js/file'
Et puis utilisez ces fonctions dans le composant comme ceci:
justAnAlert(); <p>{doSomethingWithInput('hello')}</p>
la source
/file
fin de la ligne d'importation?Si vous souhaitez manipuler l'état dans les fonctions d'assistance, procédez comme suit:
Créez un fichier Helpers.js:
export function myFunc(){ return this.state.name; //define it according to your needs }
Importez la fonction d'assistance dans votre fichier de composant:
import {myFunc} from 'path-to/Helpers.js'
Dans votre constructeur, ajoutez cette fonction d'assistance à la classe
constructor(){ this.myFunc = myFunc.bind(this) }
Dans votre fonction de rendu, utilisez-le:
render(){ <div>{this.myFunc()}</div> }
la source
Voici quelques exemples sur la façon dont vous pouvez réutiliser une fonction (
FetchUtil.handleError
) dans un composant React (App
).Solution 1: Utilisation de la syntaxe du module CommonJS
module.exports = { handleError: function(response) { if (!response.ok) throw new Error(response.statusText); return response; }, };
Solution 2: Utilisation de "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;
Remarque: si vous utilisez React v15.4 (ou une version antérieure), vous devez importer
createClass
comme suit:import React from 'react'; const FetchUtil = React.createClass({});
Source: https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#migrating-from-reactcreateclass
Composant (qui réutilise FetchUtil)
composants / 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;
la source
Une autre option solide autre que la création d'un fichier util serait d'utiliser un composant d'ordre supérieur pour créer un
withComponentMapper()
wrapper. Ce composant prendrait un composant comme paramètre et le renverrait avec lacomponentMapper()
fonction transmise comme accessoire.Ceci est considéré comme une bonne pratique dans React. Vous pouvez découvrir comment procéder en détail ici.
la source
Cela ressemble à une fonction utilitaire, dans ce cas, pourquoi ne pas la placer dans un module utilitaire statique séparé?
Sinon, si vous utilisez un transpilateur comme Babel, vous pouvez utiliser les méthodes statiques d'es7:
class MyComponent extends React.Component { static someMethod() { ...
Ou bien si vous utilisez React.createClass, vous pouvez utiliser l' objet statique :
var MyComponent = React.createClass({ statics: { customMethod: function(foo) { return foo === 'bar'; } }
Cependant, je ne conseille pas ces options, cela n'a pas de sens d'inclure un composant pour une méthode utilitaire.
De plus, vous ne devriez pas passer une méthode à travers tous vos composants comme un accessoire, cela les couplera étroitement et rendra la refactorisation plus douloureuse. Je conseille un simple module utilitaire ancien.
L'autre option est d'utiliser un mixin pour étendre la classe, mais je ne le recommande pas car vous ne pouvez pas le faire dans es6 + (et je ne vois pas l'avantage dans ce cas).
la source
React.createClass
est obsolète depuis React 15.5.0. create-react-app suggère d'utiliser le module npm à lacreate-react-class
place.doSomething.js
, ou un fichier avec plusieurs fonctions "utilitaires" similaires, par exempleutils.js
et importer ces fonctions là où vous devez les utiliserJe vais montrer deux styles ci-dessous, et vous voudrez choisir en fonction de la relation entre la logique des composants.
Style 1 - Des composants relativement liés peuvent être créés avec des références de rappel, comme ceci, dans
./components/App.js
...<SomeItem ref={(instance) => {this.childA = instance}} /> <SomeOtherItem ref={(instance) => {this.childB = instance}} />
Et puis vous pouvez utiliser des fonctions partagées entre eux comme ça ...
this.childA.investigateComponent(this.childB); // call childA function with childB as arg this.childB.makeNotesOnComponent(this.childA); // call childB function with childA as arg
Style 2 - Les composants de type Util peuvent être créés comme ceci, dans
./utils/time.js
...export const getTimeDifference = function (start, end) { // return difference between start and end }
Et puis ils peuvent être utilisés comme ça, dans
./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")); } }
Lequel utiliser?
Si la logique est relativement liée (elles ne sont utilisées que dans la même application), vous devez partager les états entre les composants. Mais si votre logique est distante (c'est -à- dire, utilitaire mathématique, utilitaire de formatage de texte), alors vous devez créer et importer des fonctions de classe util.
la source
Ne devriez-vous pas utiliser un Mixin pour cela? Voir https://facebook.github.io/react/docs/reusable-components.html
Bien qu'ils tombent en disgrâce, voir https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
Cela pourrait être utile
la source